Documento de Diseño de Base de Datos
¿Tienes dudas? No te preocupes, aquí encontrarás las soluciones.
Búsqueda Completa en el Sitio

Motor de Workflow Javascript

Todos los formularios pueden activar el motor de workflow en Javascript del lado del servidor para ejecutar lógicas empresariales complejas, tales como calcular costos y mostrar balances de inventarios. Básicamente, cualquier lógica empresarial compleja que desees ejecutar pero que no puede realizarse con las funciones actuales de Ragic puede lograrse a través de scripts del lado del servidor.

El motor de secuencias de comandos está basado en el motor de secuencia estándar Nashorn el cual está incluido en la plataforma Java. Nashron es compatible con ECMAScript 5.1, asique es preferible evitar la sintaxis ECMAScript 6.

¿Qué hace el Workflow Javascript?

El diseño de interfaz de la hoja Ragic puede realizar la mayoría de trabajo de gestión de datos, tal como crear, editar y realizar querys en registros sin mucho problema. Por otro lado, el mantenimiento manual de los datos puede consumir demasiado tiempo y volverse rutinario después de un tiempo. Este es el momento en el que los usuarios Ragic comienzan a buscar formas de automatizar estos procesos.

Dentro de Ragic, hay un motor de comando donde puedes escribir Javascript que se procesa en el lado del servidor, para recuperar datos de tu hoja, hacer modificaciones o incluso crear muchos registros con un clic. Entre los usos típicos están actualizar inventarios, crear nuevos registros según otros (crear órdenes de ventas desde una cotización, crear contactos desde leads) o validar registros según datos existentes.

Hay 5 formas principales de procesar tu workflow javascript:

  1. Botón de Acción
  2. Post-Workflow
  3. Pre-workflow
  4. Workflow Diario
  5. Workflow the Aprobación

Hay un Workflow Global en donde puedes agregar definiciones Javascript comunes compartidas por más de uno de tus scripts de workflow.

Botón de Acción

Esta es la forma más común de procesar workflow Javascript, y generalmente nuestra primera recomendación. Puedes escribir tu script en el scope instalado en hoja y configurar un botón de acción que se mostrará el panel de “Acciones” en la parte inferior derecha.

Para agregar un scope instalado en hoja, haz clic en una hoja y elige Javascript Workflow:

Y elige scope instalado en hoja desde el menú desplegable:

Puedes ir al formulario de tu diseño de hoja y agregar un Botón de Acción de tipo JS workflow, para referirse a la función Javascript que has escrito.

Nótese que puedes pasar el id del registro actual al usar {id} en el argumento para la función llamada como:

setStatus({id})

En las siguientes secciones te contamos más sobre como escribir estas funciones.

Post-workflow

Los post-workflows son ejecutados inmediatamente después que un registro es guardado. Con el post-workflow, es muy conveniente automatizar cambios que desees hacer en el registro que recién has guardado y que no pueden ser realizados con fórmulas. También puedes hacer modificaciones a registros en otras hojas relacionadas, como actualizar un balance de inventario.

Para agregar un post-workflow, sólo haz clic derecho en una hoja y elige Javascript workflow:

Elige Post-workflow desde el menú desplegable.

Un post-workflow típico se vería algo así:

var recordId = param.getNewNodeId(key_field_id_of_form);
var query = db.getAPIQuery(path_to_form);
var record = query.getAPIEntry(id);

// utiliza el registro recuperado como desees 

Vea nuestras referencias API y otras secciones de este documento para ver la lista de cosas puedes realizar.

También ten en cuenta que el post-workflow no será ejecutado si modificas registros en la página de listado.

Pre-workflow

Los pre-workflows son ejecutados antes de guardar un registro, asique puede usarse como forma de validación para verificar los datos ingresados en contraste con los datos en la base de datos. Generalmente la mayoría de validación puede realizarse con verificaciones de expresiones regulares en la interfaz del usuario (frontend), o las casillas únicas para campos de texto libre. Para verificaciones más complejas en el backend, podrías necesitas pre-workflow.

Para agregar un pre-workflow, sólo haz clic derecho en una hoja y elige Javascript workflow.

Y elige Pre-workflow desde el menú desplegable.

Aquí hay un ejemplo simple:

Supongamos que tenemos una lista,

Y queremos asegurarnos de que el precio a guardar no sea negativo.

/**

 * Key Field: 1000004

 * Field Name    Field Id
 * - - - - - - - - - - - --------
 * ID           : 1000001
 * Price        : 1000002
 * Name         : 1000003
 * Available ?  : 1000005

 */
function log(str) {
  // set status 'INVALID' or 'ERROR' to cancel the saving.
  response.setStatus('INVALID');
  response.setMessage(str);
}

function ifThePriceIsNegative() {
    // get the price we trying to save.
    var newPrice = param.getNewValue(1000002);
    // change the newPrice string to integer.
    if(parseInt(newPrice) < 0) {
      return true;
    }
}

// if the price is negative, don't save it.
if(ifThePriceIsNegative()) {
  log('Price is negative !!');
}

Ahora intentamos guardar un precio negativo, esto es lo que obtendríamos.

Nótese que no pudimos usar entry.getFieldValue al escribir el pre-workflow en Ragic (ya que Ragic no lo ha guardado). En cambio, use param para obtener el valor anterior y el nuevo valor.

Workflow Diario

El workflow diario se procesa diariamente. Es útil para hacer modificaciones que deben ser actualizadas cada día. Como, actualizar resultados de fórmulas según la fecha actual.

Para agregar un workflow diario, haz clic derecho en una pestaña y elige Javascript Workflow Global:

Y elige Workflow Diario en el primer menú desplegable.

Por defecto, el workflow diario, es ejecutado a las 19:00 UTC. Puedes cambiar la hora de ejecución y zona horaria en el Perfil de la Empresa.

1. Ve al ícono hamburguesa en la esquina superior izquierda.

2. Haz clic en Perfil de la Empresa

3. Selecciona Hora Local de la Empresa y Hora de Ejecución del Workflow Diario y guarda tus cambios.

Si tu Perfil de la empresa no tiene Hora Local de la Empresa y Hora de Ejecución del Workflow Diario, por favor contáctenos para actualizarlo.

Workflow de Aprobación

Los workflows de aprobación son ejecutados inmediatamente después de que una aprobación es creada/rechazada/cancelada/finalizada.

Para agregar un post-workflow, haz clic derecho en una hoja y elige Javascript Wokflow.

Y elige Approval workflow desde el menú desplegable.

Puedes obtener el id de registro con:

var recordId = approvalParam.getEntryRootNodeId();

approvalParam es la variable predefinida en el scope de workflow de aprobación.


Puedes realizar la acción de aprobación con:

var action = approvalParam.getApprovalAction();

Después de obtener los datos anteriores, puedes personalizar tus requerimientos así:

var query = db.getAPIQuery(path_to_form);
var entry = query.getAPIEntry(id);
if (action === 'CANCEL') {
    entry.setFieldValue(STATUS_FIELD, "approval is canceled!");
}
if (action === 'FINISH') {
    entry.setFieldValue(STATUS_FIELD, "approval is completed!");
}

Workflow Global

El workflow global es donde puedes escribir los módulos de workflow Javascript a los cuales otras funciones de workflow se pueden referir. No se ejecutará por sí solo, pero puede ser referenciado en cualquier tipo de workflow descrito anteriormente. Es adecuado para poner scripts que puedas necesitar para duplicar a través de múltiples hojas.

Para agregar un workflow global, solo haz clic derecho en una pestaña y elige Javascript Workflow Global.

Obtener Registro

Hay dos maneras diferentes de obtener el registro actual que el usuario está viendo (para botones de acción) o el registro que el usuario recién ha guardado (para pre-workflow y post-workflow).

Botón de Acción

El botón de acción de página de formulario funciona al configurar un botón de acción para llamar a la función que hayas definido en el scope de hoja. Cuando defines la función a la cual llama el botón de acción, puedes pasar el parámetro {id} el cual es el id del registro donde haces clic en el botón de acción para activar las funciones en workflow.

Puedes ver el ejemplo de Workflow de Botón de Acción.

Pre-workflow

Puedes obtener el id del registro con:

var recordId = param.getNewNodeId(key_field_id_of_form);

param es una variable predefinida, puedes usarla en el pre-workflow y post-workflow.


Después de obtener el id de registro, así es como obtienes el registro:

var query = db.getAPIQuery(path_to_form);
var entry = query.getAPIEntry(id);

Post-workflow

Para el post-workflow, puedes usar el método anterior como en el pre-worflow, pero también hay un método conveniente para recuperar el registro recién guardado:

var entry=param.getUpdatedEntry();

Si hay campos enmascarados en el formulario, obtendrás valores enmascarados por defecto. Puedes obtener los valores desenmascarados con:

var query = db.getAPIQuery(path_to_form);
query.setUpdateMode();
query.setIgnoreAllMasks(true); // desenmascara todos los campos.
var entry = query.getAPIEntry(id);

Puedes usar query.addIgnoreMaskDomain(fieldId_of_the_masked_field) en lugar de query.setIgnoreAllMasks(true) para desenmascarar campos específicos.

Hay más información sobre como actualizar registros en la siguiente sección.

Si deseas filtrar múltiples registros, por favor vea la sección sobre filtros.

Query en un Conjunto de Registros

Si quiere obtener más de un registro al filtrar:

var query = db.getAPIQuery("/workflow-demo/1");
query.addFilter(1000002, '=', 'Green');
query.addFilter(1000008, '=', '2017');
var results = query.getAPIResultList();
for (var i = 0; i < results.length; i++) {
  var entry = results[i];
  // ...
}

Puedes agregar filtros al query al addFilter(idde campo, operador, valor) y llamar a getAPIResultList() para obtener la lista de registros.

Esta es la lista de operadores que puedes usar:

Nombre del Operador Valor del Operador
Igual a =
Expresión Regular regex
Igual o mayor que
Igual o menor que <=
Mayor que
Menor que <</td>
Contiene

Debes tener en cuenta que al filtrar por fecha u hora, estos deben estar en el formato yyyy/MM/dd o yyyy/MM/dd HH:mm:ss.

También puedes usar búsqueda de texto completo como query al llamar setFullTextSearch(String queryTerm) en lugar de addFilter().

Actualizar Registros

Enlace al Ejemplo

Empezaremos con un ejemplo simple el cual obtiene el registro actual como un objeto, actualiza su valor con un botón y luego lo guarda en la base de datos. Así es como se ve el formulario de ejemplo:

Vamos a diseñar algunos botones para cambiar el valor del campo Estado con el clic de un botón al ejecutar un simple workflow Javascript del lado del servidor. Este es el código detrás del botón.

/**

 * AP_Name:wfdemo
 * Key Field: 1000013

 * Name             ID
 * - - - - - - - - - - - --------
 * No.            : 1000011
 * Status         : 1000012

 */
function setStatus(recordId, status) {

  var STATUS_FIELD = 1000012;	//field id of the status field
  var query = db.getAPIQuery("/workflow-demo/2");	//get the query object for a sheet with path to sheet
  var entry = query.getAPIEntry(recordId);	//get the record object for the current record

  //set the status value for the current record to the object
  if (status) {
	entry.setFieldValue(STATUS_FIELD, status);
  }
  else {//for switching
    var newStatus = entry.getFieldValue(STATUS_FIELD) == 'On' ? 'Off' : 'On';	//get the current value of a field
	entry.setFieldValue(STATUS_FIELD, newStatus);
  }

  //save the record back to the database
  entry.save();
}

Al escribir workflow Javascript, la variable db es predefinida. Puedes referenciarla donde sea. Generalmente llamamos al método getAPIQuery(pathName) para recuperar el objeto query para una hoja.

Luego puedes recuperar un registro con su id de registro en la hoja objeto con getAPIEntry(recordId) y llamar setFieldValue(fieldId,value) para fijar el valor a un campo o getFieldValue(fieldId) para recuperar el valor de un registro.

Por favor tenga en cuenta que, al agregar valores, debe ser en uno de los siguientes formatos:

yyyy/MM/dd

yyyy/MM/dd HH:mm:ss

HH:mm:ss

Si estas recuperando un valor de un campo de selección múltiple, donde puede haber múltiples valores, usa getFieldValues(fieldId) para recuperar todos los valores en una matriz. También puedes llamar setFieldValue(fieldId,value,true) con un argumento true extra al final para especificar que estás “agregando” una opción a la lista actual de valores, no sobrescribiendo los existentes. Nótese que estas operaciones solo son adecuadas para campos de selección múltiple.

Si deseas copiar el valor de un campo de selección múltiple y sobrescribir el valor en otro campo de selección múltiple, no puedes usar getFieldValues(fieldId) y setFieldValue(fieldId,value,true). Este es el código al que debes referirte:


var multipleSelectionFieldValue = entry.getFieldValues(1013251); // 1013251 is a mutiple selection field 

var targetMultipleSelectionField = "";

for (var i = 0; i < multipleSelectionFieldValue.length; i++) {  
  
        if (i == 0) {
          
          targetMultipleSelectionField = targetMultipleSelectionField + multipleSelectionFieldValue[i];
          
        } 
  
        else {
        
          targetMultipleSelectionField = targetMultipleSelectionField + "|" + multipleSelectionFieldValue[i];
          
        }
        
}

entry.setFieldValue(1013252, targetMultipleSelectionField, false); // 1013251 is another mutiple selection field 

Por favor ten en cuenta que debes recuperar cada opción y separarlas con una barra vertical (|) como lo harías al importar datos desde documentos Excel o CSV.

Si estás fijando valores a un campo de archivo adjunto, puede usar setFieldFile(int fieldId, String fileName, String fileContent) para crear un documento con el nombre del archivo (fileName) y contenido (fileContent) que indiques. Ragic guardará este documento para que esté disponible para descargarse desde la interfaz del usuario.

Cuando hayas terminado, llama save() en el objeto del registro para guardarlo de nuevo a la base de datos.

Crear Registros

Crear registros es muy similar a actualizar registros. En lugar de llamar a query.getAPIEntry(), llama a query.insertAPIEntry(). Al igual que getAPIEntry(), también devolverá un registro donde puedes agregar valores de campo con setFieldValue. El registro será creado después de llamar record.save().

Una simple modificación de la actualización del registro creará un nuevo registro:

/**

 * AP_Name:wfdemo
 * Key Field: 1000013

 * Name             ID
 * - - - - - - - - - - - --------
 * No.            : 1000011
 * Status         : 1000012

 */
function setStatus(recordId, status) {

  var STATUS_FIELD = 1000012; //field id of the status field
  var query = db.getAPIQuery("/workflow-demo/2"); //get the query object for a sheet with path to sheet
  var entry = query.insertAPIEntry();  //create a new record object

  //create the new record to the database
  entry.save();
}

Subtablas

Enlace al ejemplo

Si tienes subtablas en una hoja, puedes usar nuestra API para recuperar datos de ella o hacer ediciones como en el siguiente ejemplo. El formulario se ve así:

El workflow te guiará a través de cada fila de la subtabla, encontrará la cantidad total para ese año (según el campo de fecha en la subtabla), el total máximo para ese año, y el año que tuvo el total más alto. Esto está diseñado como un post-workflow, asique los tres campos de sólo lectura, serán rellenados por el workflow después de que el registro sea guardado.

/**

 * AP_Name:wfdemo
 * Key Field: 1000006

 * Date subtable key: 1000007

 * Field Name               Field Id
 * - - - - - - - - - - - --------
 * No.                     : 1000001
 * Name                    : 1000002
 * Date                    : 1000003
 * Amout                   : 1000004
 * Total of This Year      : 1000010
 * Maximal Total of Year   : 1000009
 * Year of Maximal Total   : 1000008

 */

var KEY_FIELD             = 1000006;
var AMOUNT_SUBTABLE_ID    = 1000007;
var DATE_FIELD            = 1000003;
var AMOUNT_FIELD          = 1000004;
var MAX_YEAR_FIELD        = 1000008;
var MAX_TOTAL_FIELD       = 1000009;
var THIS_YEAR_TOTAL_FIELD = 1000010;

var query = db.getAPIQuery("/workflow-demo/1");

var entry = query.getAPIEntry(param.getNewNodeId(KEY_FIELD));
var subtableSize = entry.getSubtableSize(AMOUNT_SUBTABLE_ID);

var yearTotal = {}
for (var i = 0; i < subtableSize; i++) {
  	var year = parseInt(entry.getSubtableFieldValue(AMOUNT_SUBTABLE_ID, i, DATE_FIELD).substr(0, 4));
	var amount = parseInt(entry.getSubtableFieldValue(AMOUNT_SUBTABLE_ID, i, AMOUNT_FIELD));
	if (year in yearTotal) {
		yearTotal[year] += amount;
	} else {
		yearTotal[year] = amount;
	}
}

var maxYear;
for (var year in yearTotal) {
	if (!maxYear || yearTotal[maxYear] < yearTotal[year]) {
		maxYear = year;
	}
}

entry.setFieldValue(MAX_YEAR_FIELD, maxYear);
entry.setFieldValue(MAX_TOTAL_FIELD, yearTotal[maxYear]);
entry.setFieldValue(THIS_YEAR_TOTAL_FIELD, yearTotal[new Date().getFullYear()]);
entry.save();

La idea básica es usar getSubtableSize(subtableId) para obtener el número de filas para un registro, y usar getSubtableFieldValue(subtableId,subtableRowIndex,subtableFieldId) para obtener sus valores. Puedes encontrar el id de subtabla y el id campo en los comentarios autogenerados al iniciar la edición del script de workflow.

También puedes usar setSubtableFieldValue(subtableFieldId,subtableRootNodeId,value) para fijar valores a una subtabla. El subtableRootNodeId se usa para especificar a cual fila de subtabla te estás refiriendo. Para encontrar el subtableRootNodeId de una fila de subtabla existente, puedes usar la siguiente llamada getSubtableRootNodeId(subtableId,subtableRowIndex) la cual devolverá un número entero con el subtableRootNodeId.

Si necesitas agregar una fila a la subtabla, puedes usar un subtableRootNodeId negativo como -100, de esta manera todos los valores fijados al mismo subtableRootNodeId negativo serán aplicados en la misma nueva fila de subtabla y los valores fijados a un subtableRootNodeId negativo diferente como -101 crearán una fila diferente en la subtabla con un set diferente de valores.

Pre-workflow y Post-workflow

Si deseas obtener valores en pre-workflow y post-workflow, prueba el siguiente ejemplo:

var list = param.getSubtableEntry(AMOUNT_SUBTABLE_ID);
var arr = list.toArray();
response.setStatus('WARN');
for (var i = 0; i < arr.length; i++) {
  response.setMessage('Date : '+arr[i].getNewValue(DATE_FIELD)+', Amount : '+arr[i].getNewValue(AMOUNT_FIELD)+'\r\n');
}

Copiar Registros

Enlace a ejemplo: Copiar de y Copiar a

Copiar registros es uno de los programas de workflow más comunes que encontramos. Hemos escrito una función muy sencilla para simplificar este tipo de operación. Supongamos que queremos ver un registro en esta hoja:

Con un el clic de un botón, generar un registro en esta hoja:

Este es el código para este botón de acción:

/**

 * AP_Name:wfdemo
 * Key Field: 1000022

 * S1 subtable key: 1000023
 * T1 subtable key: 1000029

 * Field name    Field ID
 * - - - - - - - - - - - --------
 * A              : 1000014
 * C              : 1000015
 * B              : 1000016
 * D              : 1000017
 * S1             : 1000018
 * S2             : 1000019
 * S3             : 1000020
 * S4             : 1000021
 * T1             : 1000024
 * T2             : 1000025
 * T3             : 1000026

 */

function copyEntry(nodeId) {

  db.entryCopier(JSON.stringify({
    THIS_PATH:"/workflow-demo/3",
    THIS_NODEID:nodeId,
    NEW_PATH:"/workflow-demo/4",
    COPY:{
      1000030:1000014,    // A
      1000031:1000015,    // C
      1000032:1000018,    // S1
      1000033:1000020     // S3
    }
  }),response);
}

Aquí puedes ver que la copia puede realizarse con una simple función para llamar a entryCopier. entryCopier toma una cadena JSON como su parámetro. Solo indica la hoja fuente, la hoja destino, el registro que deseas copiar y lo más importante, cuál campo debe ser mapeado a qué campo. Cuando el mapeo esté completo, puedes crear botones de acción para copiar los registros de una hoja a otra muy fácilmente.

Veamos otro ejemplo.

Aquí, queremos copiar Lin desde "CopyFrom" a "CopyTo" y fijar el estado como nuevo. Además, también queremos registrar la fecha de creación (puedes ignorar el uso del campo fecha para este ejemplo).

/**
 * field name      field id
 * - - - - - - - - - - - --------
 * From-ID        : 1000001
 * From-Name      : 1000002
 * To-ID          : 1000004
 * To-Name        : 1000005
 * Status         : 1000007
 * RegisterDate   : 1000008
 */

function copyEntry(nodeId) {
  db.entryCopier(JSON.stringify({
    THIS_PATH:"/entrycopier/1",
    THIS_NODEID:nodeId,
    NEW_PATH:"/entrycopier/2",
    COPY:{
      //       to  :  from
      1000004:1000001,   
      1000005:1000002,   
    }
  }),response);
  //get the rootNodeId of the entry we copied before.
  var newEntryRootNodeId = response.getRootNodeId();
  //we need to create an ApiQuery to search the '/entrycopier/2'
  var toApiQuery = db.getAPIQuery('/entrycopier/2');
  //get the entry we copied before
  var newEntry = toApiQuery.getAPIEntry(newEntryRootNodeId);
  newEntry.setFieldValue(1000007, "New");
  var current = new Date();
  newEntry.setFieldValue(1000008, current.getFullYear()+'/' + (current.getMonth()+1) + '/' + current.getDate());
  newEntry.save();
}

Siguiente, configura el Botón de Acción y guárdalo.

Luego, haz clic en el Botón de Acción para mostrar el resultado.

Verificar los Derechos de Acceso del Usuario

Puedes realizar algunos procesos condicionales según el grupo de usuarios en el que se encuentre el usuario quien ejecuta el script. Un usuario puede estar en múltiples grupos, asique usualmente puedes hacer una llamada user.isInGroup(groupName) para determinar si el usuario está o no en ese grupo. Un uso típico sería el siguiente, el siguiente código está diseñado para ser un pre-workflow, pero el usuario objeto y la llamada isInGroup pueden usarse en todos los tipos de workflow excepto en el workflow diario el cual es activado por el sistema.

if(!user.isInGroup('SYSAdmin')){//check if the user is a SYSAdmin
  response.setStatus('INVALID');//if they are not, do not save the record
  response.setMessage('You do not have the access right to do this.');//and display a message
}

Enviar Notificaciones por Correo

Algunas veces quizá desees enviar notificaciones por correo según algunas condiciones, o quizá desees personalizar el contenido del mensaje de notificación. Puedes escribir un workflow Javascript en el lado del servidor para lograrlo. Aquí hay un script que puedes usar para enviar notificaciones por correo, es muy simple:


//omitted...retrieve record object first

var name=entry.getFieldValue(1001426);
var email=entry.getFieldValue(1001428);
var title=entry.getFieldValue(1001386);

mailer.compose(
    email,	//to
    null,	//cc
    'support@example.com',	//reply to
    'Acme, Inc.',  //displayed from
    title,
    'Hi '+name+',

we have received your sales order '+ 'and will be processing your order very soon.

'+ 'You can see your order details at https://www.ragic.com/example/1

'+ 'Thanks.


Best Regards,

Sophia, Sales Manager

Acme, Inc.' ); //mailer.attach(myURL); //you can use .attach to attach content from a URL mailer.send();

Nótese que, si deseas enviar el correo a múltiples destinatarios, solo debes separar cada dirección de correo usando comas.

En cuanto a documentos adjuntos puedes usar mailer.attach(myURL); para adjuntar un registro en Ragic usando el URL del registro. Por ejemplo, aquí hay un URL de Ragic (siempre ignore el URL después del hash)

https://www.ragic.com/wfdemo/workflow-demo/2/9

Este es el URL print friendly HTML:

https://www.ragic.com/wfdemo/workflow-demo/2/9.xhtml

Este es la versión Excel del URL:

https://www.ragic.com/wfdemo/workflow-demo/2/9.xlsx

También puedes usar la combinación de correspondencia así, el cid es el id de la combinación de correspondencia, puedes obtener el cid en el URL al intentar descargar el documento de combinación de correspondencia:

https://www.ragic.com/wfdemo/workflow-demo/2/9.custom?rn=9&cid=1

Ragic tiene limitaciones en la cantidad de correos puedes enviar. ¡Asique envíalos razonablemente! Si tienes preguntas sobre los límites de envío, contáctenos a support@ragic.com.

Crear o Cancelar una Aprobación

Puedes iniciar o cancelar la aprobación de un registro al agregar un script post-workflow a tu hoja.

Primero, fijaremos el paso de aprobación en el modo diseño.

Luego los detalles de aprobación en el post-workflow

function autoStartApprover() {
  var signers = [];
  signers.push({
    'stepIndex':'0',
    'approver':'kingjo@ragic.com',
    'stepName':'START'
  });
  signers.push({
    'stepIndex':'1',
    'approver':'HR0000@hr.hr',
    'stepName':'HR'
  });
  
  approval.create(JSON.stringify(signers));
}

autoStartApprover();

resultado

{
    'stepIndex':'0',
    'approver':'kingjo@ragic.com',
    'stepName':'START'
}

Este el formato de parámetro que debes proveer.

stepIndex :

Es usado para saber cuál paso de aprobación fijar, iniciando de cero.

approver :

Es usado para saber quién podría firmar este paso de aprobación.

stepName :

Es usado para fijar el nombre al paso de aprobación.

Tu aprobación no se creará si hay algo mal en el formato del parámetro o si los aprobadores que indiques no cumplen la regla fijada en el modo diseño.

En este ejemplo, si tu segundo parámetro es

{
    'stepIndex':'1',
    'approver':'kingjo@ragic.com',
    'stepName':'HR'
}

,este fallaría, ya que kingjo@ragic.com no es parte del grupo HR.

También brindamos 3 formatos especiales para decidir tus aprobadores dinámicamente según tu árbol empresarial.

Puedes ver aquí para más información.

$DS :

El aprobador será fijado al supervisor directo del usuario.

$SS :

El aprobador será fijado al supervisor del supervisor.

$DSL :

El aprobador será fijado al supervisor del aprobador anterior.

El parámetro del formato es

{
    'stepIndex':'1',
    'approver':'$DSL',
    'stepName':''
}

No necesitas proveer un stepName no vacío al usar estos formatos especiales.

Nota: si el usuario en el formato especial no cumple la regla fijada en el modo diseño, este aprobador no será creado.

Enviar Notificaciones a la Aplicación Móvil

Además de las notificaciones por correo, también puedes enviar notificaciones a la aplicación móvil. Serán enviadas al usuario si la aplicación iOS o Android ha sido instalada en su dispositivo móvil. El correo se refiere a la dirección del usuario registrada en tu cuenta Ragic. Por ejemplo:

mailer.sendAppNotification("mike@example.com","test mobile notification");

Si deseas que el usuario sea redireccionado al registro especificado al hacer clic en esta notificación, debes indicar la ruta al formulario al que deseas redireccionar (ej: /forms/1 y el id de registro. La llamada debe verse así:

mailer.sendAppNotification("mike@example.com","test mobile notification","/forms/1",12);

Aprobación y otra Información del Registro

Primero puedes enviar el siguiente comando al objeto de query que recibas de db.getAPIQuery para incluir toda la información del registro:

query.setIfIncludeInfo(true);

Y después puedes obtener la información de aprobación para el registro así:

entry.getFieldValue('_approve_status');//Obtiene el estado de la aprobación actual
entry.getFieldValue('_approve_next');//Obtiene el siguiente usuario que debe firmar
entry.getFieldValue('_create_date');//Obtiene la fecha de creación del registro
entry.getFieldValue('_create_user');//Obtiene el correo del usuario quien creó el registro

El estado de aprobación será F si es aprobado, REJ si es rechazado, P para procesando.

Mostrar Mensaje

Puedes mostrar un mensaje en una ventana emergente. Por favor tome en cuenta que el mensaje sólo se mostrará cuando el estado de respuesta es “WARN”. Por defecto, el mensaje dentro de la respuesta no se mostrará ya que usualmente no es de utilidad a los usuarios finales.

response.setStatus('WARN');
response.setMessage(message);

Paginación

En esta sección te mostraremos como usar setLimitSize y setLimitFrom. En este ejemplo tenemos 20 registros en total, y queremos tomar 6 para cada conteo y muestra el mensaje.

/**

 * Field Name    Field Id
 * - - - - - - - - - - - --------
 * ID           : 1000009
 * Money        : 1000010

 */
function limitFromExample() {
    var apiQuery = db.getAPIQuery('/entrycopier/3');
    // remember the offset
    var fromNumber = 0;
    apiQuery.setLimitFrom(fromNumber);
    // take 6 for each count
    apiQuery.setLimitSize(6);
    var resultList = apiQuery.getAPIResultList();
  
    while(resultList.length > 0) {
        var msg = ''; 
        for(var i = 0;i < resultList.length; i++) {
            var entry = resultList[i];
            msg += entry.getFieldValue(1000009);
            if(i != resultList.length -1)  msg += ',';
        }
        response.setMessage(msg);
        // update offset
        fromNumber += resultList.length;
        // refresh apiQuery
        apiQuery = db.getAPIQuery('/entrycopier/3');
        apiQuery.setLimitSize(6);
        apiQuery.setLimitFrom(fromNumber);
        resultList = apiQuery.getAPIResultList();
    }
    response.setStatus('WARN');
}

Registros

Resultado

Enviar Solicitud HTTP

Puedes enviar una solicitud HTTP GET/POST/DELETE/PUT a un URL y obtener el resultado:

util.getURL(String urlstring)  
util.postURL(String urlstring,String postBody)
util.deleteURL(String urlstring)
util.putURL(String urlstring,String putBody)

La variable util es predefinida.

También puedes llamar util.setHeader(String name,String value) para fijar encabezados HTTP, y util.removeHeader(String name) para quitar los encabezados.

Referencias API

Puedes acceder directamente a las variables globales predefinidas en el sistema sin definirlas.

db.getAPIQuery

MétodoDescripción
getAPIResult()Obtiene el primer registro al iterar sobre el query
getAPIResultList()Obtiene una matriz de registros del query
getAPIEntry(int rootNodeId)Obtiene el registro por ID de nodo
getKeyFieldId()Obtiene el id del campo clave de la hoja en la que se realiza la query
getFieldIdByName(String fieldName)Obtiene el id del campo de un nombre especificado. Si hay más de un campo del mismo nombre, el id del primer campo independiente será devuelto.
insertAPIEntry()Inserta un nuevo registro al query, el método devuelve el nuevo registro.
addFilter(int fieldId, String operand, String value)Filtra los registros por una condición especificada.
setIfIgnoreFixedFilter(boolean ifIgnoreFixedFilter)()Fijar si deseas ignorar la vista fija de la hoja destino.
setOrder(int orderField, int orderDir)Ordena los registros del query por el id de campo especificado y orden de dirección especificado, parámetro orderDir se fija a 1 para orden ascendente y se fija a 2 para orden descendente.
deleteEntry(int nodeId)Eliminar un registro por ID de nodo
setLimitSize(int limitSize)Por defecto, ScriptAPIQuery devuelve 1000 registros por query, puedes usar setLimitSize para cambiar el número de registros devueltos por el query. Sin embargo, no recomendamos devolver muchos registros por query ya que podría usar mucha memoria y podría tener implicaciones en rendimiento. Recomendamos usar el siguiente método setLimitFrom para realizar paginado.
setLimitFrom(int limitFrom)Este método es para paginar a través de todos los registros en un ScriptAPIQuery. Al configurar un limitFrom se le indica al ScriptAPIQuery que inicie la devolución de registros con un límite para que puedas paginar todos los registros de ScriptAPIQuery, ya que por defecto, devolverá 1000 registros por query. Puedes revisar por una siguiente página si el número de registros devueltos equivale al tamaño de la lista devuelta.
setGetUserNameAsSelectUserValue(boolean b)Cuando es fijado a false, el query recuperará el correo del usuario, de los campos de tipo seleccionar usuario en lugar del nombre del usuario.

Esta es la lista de operadores que puedes usar:

Nombre del Operador Valor del Operador
Igual a =
Expresión Regular regex
Igual o mayor que
Igual o menor que <=
Mayor que
Menor que <</td>
Contiene like

Debes tener en cuenta que al filtrar por fecha u hora, estos deben estar en el siguiente formato yyyy/MM/dd o yyyy/MM/dd HH:mm:ss.

También puedes usar búsqueda de texto completo como filtro de query al llamar setFullTextSearch(String queryTerm) en lugar de addFilter().

db.getAPIQuery records

MétodoDescripción
getFieldValue(int fieldId)Obtiene el valor del campo a través del id de campo. No incluye campos de subtabla.
getFieldIdByName(String fieldName)Obtiene el id de campo de un nombre especificado. Si hay más de un campo con el mismo nombre, el primer id del campo independiente será devuelto.
getKeyFieldId()Devuelve el id de campo de esta hoja.
getFieldValueByName(String fieldName)Obtiene el valor del campo a través del nombre de campo. No incluye campos de subtabla. Si hay más de un campo con el mismo nombre, el valor del primer campo será devuelto.
getFieldValues(int fieldId)Obtiene todos los valores de campo de un campo de selección múltiple en un matriz. No incluye campos de subtabla.
getRootNodeId()Obtiene el id de nodo del registro
getRootfieldId()Obtiene el id de campo root del registro
getSubtableSize(int subtableRootfieldId)Obtiene el tamaño de subtabla, especificado por el id de campo root de subtabla.
getSubtableRootNodeId(int subtableRootfieldId, int rowNumber)Obtiene el id de nodo root de subtabla, especificado por su id de campo root y número de fila en subtabla.
getJSON()Obtiene una representación JSON de todo el registro.
setFieldValue(int fieldId, String value)Fija valor a un campo especificado. Para campos de subtabla, necesitas usar setSubtableFieldValue();
setFieldValue(int fieldId, String value, boolean appendValue)Fija valor a un campo de selección múltiple, el parámetro appendValue debe ser true. Para campos de subtabla, necesitas usar setSubtableFieldValue();
setFieldFile(int fieldId, String fileName, String fileContent)Para campos de archivos adjuntos o gráficos. Un documento del fileName que y el fileContent hayas indicado se creará como archivo adjunto y se guardará en el campo especificado. Para campos de subtabla, debes usar setSubtableFieldFile();

setSubtableFieldValue(int fieldId, int subtableRootNodeId,String value)Fija valor a un campo de subtabla, puedes obtener el parámetro subtableRootNodeId a través del método getSubtableRootNodeId.
setSubtableFieldValue(int fieldId, int subtableRootNodeId, String value, boolean appendValue)Fija valor a un campo de subtabla el cual es de selección múltiple, el parámetro appendValue debe ser true
deleteSubtableRowByRowNumber(int subtableRootfieldId, int rowNumber)Elimina una fila de subtabla a través del id de campo root y el número de fila de subtabla.
deleteSubtableRowAll(int subtableRootfieldId)Elimina cada fila de una subtabla especificada.
deleteSubtableRow(int subtableRootfieldId, int subtableRootNodeId)Elimina fila de subtabla a través de id de campo root y id de nodo root de subtabla
loadAllLinkAndLoad()Carga los valores de todos los campos cargados en una configuración de enlazar y cargar en el registro.
recalculateAllFormulas()Recalcula cada campo que contiene una fórmula en el registro.
recalculateFormula(int fieldId)Recalcula la fórmula de un campo especificado.

Nota: si dos o más campos comparten el mismo ID de campo (fieldId), por favor usa recalculateFormula(int fieldId, String cellName).

recalculateFormula(int fieldId, String cellName)Recalcula la fórmula de un campo especificado usando el parámetro cellName determinado la ubiación de la celda (tal como A1, C2, H21, etc). Este método es usado en hojas con dos o más campos con el mismo ID de campo (fieldId).
loadAllDefaultValues(ScriptUser user)Carga los valores de cada campo que está fijado como valor predeterminado, el parámetro user es predefinido.
loadDefaultValue(int fieldId, ScriptUser user)Carga el valor predeterminado de un campo especificado, el parámetro user es predefinido
lock()Bloquea el registro
unlock()Desbloquea el registro
save()Guarda un registro
setCreateHistory(boolean createHistory)Fijar si el registro debe crear historial
isCreateHistory()Si el registro está configurado para crear historial
setIfExecuteWorkflow(boolean executeWorkflow)Fijar si ejecutar workflow (pre-workflow y post-workflow) del registro es necesario.
setIgnoreEmptyCheck(boolean ignoreEmptyCheck)Fijar si la verificación de campos no vacíos debe ser ignorada
setRecalParentFormula(boolean recalParentFormula)Si esta hoja es creada por una subtabla de otra hoja, o es referenciada por otra hoja lo cual indica que esta hoja tiene una hoja madre, puedes llamar este método para fijar si deseas recalcular la hoja madre o no.
setIfDoLnls(boolean)Se activará la sincronización de valores cargados en la otra hoja si está enlazada a esta, la hoja fuente. Siempre debes agregar este método a la hoja fuente para activar sincronización en la otra hoja.

respuesta

MétodoDescripción
getStatus()Obtiene el estado de la respuesta. Ya sea SUCCESS, WARN, CONFIRM, INVALID, ERROR
setStatus(String status)Fija el estado de la respuesta. Ya sea, SUCCESS, WARN, CONFIRM, INVALID, ERROR
setMessage(String plainMessage)Fija un mensaje a mostrar al ejecutar el script. Esta función puede ser llamada varias veces y todos los mensajes fijados se mostrarán al mismo tiempo.
numOfMessages()Devuelve el número de mensajes que hayan sido fijados.
setOpenURL(String url)Solo scope instalada en hoja. Redirecciona el usuario al URL especificado después de guardar la edición.
setOpenURLInNewTab(boolean b)Configura el explorador para abrir una nueva pestaña al abrir un URL. Predeterminado a true.

usuario

MétodoDescripción
getEmail()Obtiene la dirección de correo del usuario
getUserName()Obtiene el nombre completo del usuario
isInGroup(String groupName)Devuelve si el usuario está en este grupo con el nombre de groupName

mailer

MétodoDescripción
compose(String to,String cc,String from,String fromPersonal,String subject,String content)Crea un mensaje de correo para enviar. Los parámetros to y cc pueden tener múltiples direcciones de correo, las cuales deben estar separadas por comas.
send()Envía el mensaje que recién ha sido creado.
sendAsync()Envía el mensaje que recién ha sido creado asincrónicamente. Nótese que sendAsync solo puede ser llamada una vez por ejecución de script.
attach(String url)Adjunta un documento al mensaje. El URL debe ser un URL completo con https://
setSendRaw(boolean b)Fija si el contenido no debe ser convertido a HTML. Fija a true cuando tu contenido ya está en HTML.
sendAppNotification(String email,String message)Envía una notificación a la aplicación Ragic de este usuario si ha instalado la aplicación iOS o Android en su móvil.
sendAppNotification(String email,String message,String pathToForm,int nodeId)Envía una notificación a la aplicación Ragic de este usuario si ha instalado la aplicación iOS o Android en su móvil. El usuario será redireccionado al registro especificado al hacer clic en esta notificación. "pathToForm" debe estar en este formato "/forms/1", sin incluir el nombre de cuenta, pestaña e índice de hoja.

util

MétodoDescripción
getURL(String urlstring)Llama un URL con el método GET.
postURL(String urlstring,String postBody)Llama un URL con el método POST.
deleteURL(String urlstring)Llama un URL con el método DELETE.
putURL(String urlstring,String putBody)Llama un URL con el método PUT.
setHeader(String name,String value)Fija un encabezado HTTP que será usado en llamadas URL subsecuentes.
removeHeader(String name)Quita un encabezado HTTP para que deje de ser usado en llamadas URL subsecuentes.
logWorkflowError(String text)Registra una cadena de texto de mensaje registro en el registro de workflow el cual puedes encontrar en la página de Mantenimiento de base de datos.

cuenta

MétodoDescripción
getUserName(String email)Obtiene el nombre completo de un usuario especificado por la dirección de correo.
getUserEmail(String userName)Obtiene la dirección de correo de nombre de usuario especificado.
reset()Elimina la cache relacionada a tu cuenta cuando el script actualiza la página y termina la ejecución.
getTimeZoneOffset()Obtiene la diferencia de zona horaria de esta cuenta en milisegundos.
getTimeZoneOffsetInHours()Obtiene la diferencia de zona horaria de esta cuenta en horas.

param

Este es el objeto de solicitud enviada por el usuario antes de que la solicitud sea guardada en la base de datos. Especialmente útil al escribir scripts de pre-workflow.

MétodoDescripción
getUpdatedEntry()Sólo para post-workflow. Devuelve el registro que recién ha sido creado o actualizado.
getNewNodeId(int fieldId)Devuelve el ID de nodo (int) de un campo dado después de que un valor nuevo haya sido escrito.
getOldNodeId(int fieldId)Devuelve el ID de un nodo (int) de un campo dado antes de que un nuevo valor sea escrito.
getNewValue(int fieldId)Devuelve el valor de un campo dado después de que un nuevo valor sea escrito.
getOldValue(int fieldId)Devuelve el valor de un campo dado antes de que un nuevo valor sea escrito.
getNewValues(int fieldId)Similar a getNewValue, pero puedes acceder a múltiples valores al mismo tiempo, lo cual es muy útil al manejar campos de selección múltiple.
getOldValues(int fieldId)Similar a getOldValue, pero puedes acceder a múltiples valores al mismo tiempo, lo cual es muy útil al manejar campos de selección múltiple.
getSubtableEntry(int fieldId)Devuelve una lista de parámetros que pueden manipular cada registro en la subtabla.
isCreateNew()Devuelve si el registro ha sido creado recientemente.

aprobación

MétodoDescripción
create(String[] wfSigner)

wfSigner es una matriz con objetos en formato JSON en ella.

{

'stepIndex' : cuál paso en la aprobación- iniciando desde 0,

'approver' : dirección de correo del aprobador

'stepName' : nombre o título del aprobador

}

El ejemplo para "aprobador individual en un paso" :

wfSigner push({

'stepIndex':'1',

'approver':'kingjo@ragic.com',

'stepName':'Jo'

})

Nótese que el wfSigner debe cumplir con la aprobación fijada en el modo diseño.

Por ejemplo, si solo hay un candidato "HR00@gmail.com" en el paso 2 del modo diseño, debes indicar json con el aprobador : HR00@gmail.com y stepIndex : 1 .

cancel()Sólo post-workflow. Cancela la aprobación en el registro.

approvalParam

MétodoDescripción
getEntryRootNodeId()Obtiene el ID de nodo root del registro
getApprovalAction()Obtiene la acción de la aprobación. Ya sea, CREATE, FINISH, CANCEL, REJECT.

Volver arriba Tabla de contenido

Iniciar Ragic Gratis

Registrarse con Google