Saltar para o conteúdo principal

Referencia de Scripting

Este documento fornece uma referencia abrangente para escrever scripts em regras de workflow. Os scripts permitem-lhe implementar logica de automacao avancada usando JavaScript.


Visao Geral​

A acao Run Script em regras de workflow executa codigo JavaScript para automatizar cenarios complexos de tratamento de tickets. Os scripts sao executados num ambiente isolado com acesso a dados de tickets, contexto de mensagens e funcoes auxiliares.

Funcionalidades principais:

  • Ler e modificar propriedades de tickets
  • Aceder a informacoes de clientes e proprietarios
  • Trabalhar com campos personalizados
  • Usar logica condicional e loops
  • Timeout de execucao de 10 segundos para seguranca

Objeto Ticket​

O objeto ticket e o contexto principal para os seus scripts. Fornece acesso de leitura e escrita aos dados do ticket.

Propriedades So de Leitura​

// Informacao basica do ticket
ticket.id // String UUID
ticket.subject // Linha de assunto do ticket

// Estado atual (objeto)
ticket.status.id // UUID do estado
ticket.status.code // Codigo do estado (por exemplo, "open", "closed")
ticket.status.name // Nome de exibicao do estado

// Prioridade atual (objeto)
ticket.priority.id // UUID da prioridade
ticket.priority.name // Nome de exibicao da prioridade

// Departamento atual (objeto)
ticket.department.id // UUID do departamento
ticket.department.name // Nome de exibicao do departamento

// Proprietario atribuido (objeto, pode ser undefined)
ticket.owner.id // UUID do utilizador
ticket.owner.email // Email do utilizador
ticket.owner.firstname // Primeiro nome do utilizador
ticket.owner.lastname // Ultimo nome do utilizador

// Informacao do cliente (objeto)
ticket.customer.id // UUID do cliente
ticket.customer.email // Email do cliente
ticket.customer.firstname // Primeiro nome do cliente
ticket.customer.lastname // Ultimo nome do cliente
ticket.customer.name // Nome completo do cliente

// Pasta e tags
ticket.folder // Pasta atual: "INBOX", "ASSIGNED", "SPAM", "ARCHIVE"
ticket.tags // Array de strings de tags

Propriedades Gravaveis​

Pode modificar estas propriedades por atribuicao direta:

// Definir estado por codigo ou ID
ticket.status = "closed";
ticket.status = "550e8400-e29b-41d4-a716-446655440000";

// Definir prioridade por nome ou ID
ticket.priority = "High";
ticket.priority = "550e8400-e29b-41d4-a716-446655440001";

// Definir departamento por nome ou ID
ticket.department = "Sales";
ticket.department = "550e8400-e29b-41d4-a716-446655440002";

// Definir proprietario por email ou ID
ticket.owner = "[email protected]";
ticket.owner = "550e8400-e29b-41d4-a716-446655440003";

// Definir pasta
ticket.folder = "ASSIGNED";
ticket.folder = "SPAM";
ticket.folder = "ARCHIVE";
ticket.folder = "INBOX";

// Definir tags (substitui todas as tags existentes)
ticket.tags = ["urgent", "vip"];

Campos Personalizados​

Os campos personalizados podem ser lidos e escritos usando o seu codigo (nao o nome de exibicao).

Ler Campos Personalizados​

// Aceder ao valor do campo personalizado diretamente
var orderId = ticket.order_id; // Campo de texto
var amount = ticket.order_amount; // Campo numerico
var isVip = ticket.is_vip; // Campo booleano
var region = ticket.region; // Campo de selecao

Escrever Campos Personalizados​

// Definir campo personalizado de texto
ticket.order_id = "ORD-12345";

// Definir campo personalizado numerico
ticket.order_amount = 199.99;

// Definir campo personalizado booleano
ticket.is_vip = true;

// Definir campo personalizado de selecao
ticket.category = "billing";

// Definir campo personalizado de data (formato ISO 8601)
ticket.due_date = "2024-12-31T23:59:59Z";
ticket.due_date = "2024-12-31";

Objeto Message​

O objeto message esta disponivel quando a regra e acionada por um evento de mensagem (New Customer Reply, New Staff Reply, etc.).

if (message) {
message.id // UUID da mensagem
message.body_text // Conteudo da mensagem (texto simples)
message.body_html // Conteudo da mensagem (HTML)
message.createdAt // Timestamp ISO 8601
}

Exemplo:

if (message && message.body_text) {
var bodyLower = message.body_text.toLowerCase();

if (bodyLower.includes("cancel subscription")) {
ticket.department = "Retention";
ticket.priority = "High";
}
}

Funcoes Auxiliares​

getStatuses()​

Retorna um array de todos os estados disponiveis.

var statuses = getStatuses();
// Retorna: [{ id: "...", code: "open", name: "Open" }, ...]

// Encontrar um estado especifico
for (var i = 0; i < statuses.length; i++) {
if (statuses[i].code === "pending") {
ticket.status = statuses[i].id;
break;
}
}

getPriorities()​

Retorna um array de todas as prioridades disponiveis.

var priorities = getPriorities();
// Retorna: [{ id: "...", name: "Low" }, { id: "...", name: "High" }, ...]

getDepartments()​

Retorna um array de todos os departamentos disponiveis.

var departments = getDepartments();
// Retorna: [{ id: "...", name: "Support" }, { id: "...", name: "Sales" }, ...]

getUsers()​

Retorna um array de todos os utilizadores disponiveis (agentes).

var users = getUsers();
// Retorna: [{ id: "...", email: "[email protected]", firstname: "John", lastname: "Doe" }, ...]

fetch()​

Faz pedidos HTTP a APIs externas. Sincrono - retorna resultado diretamente.

var response = fetch(url, options);
// response: { ok, status, statusText, text, json }

Opcoes: method (GET/POST/PUT/DELETE), headers (objeto), body (string ou objeto)

Exemplo: Buscar de CRM e atualizar campos personalizados

var response = fetch("https://api.example.com/customers/" + ticket.customer.email, {
headers: { "Authorization": "Bearer YOUR_API_KEY" }
});

if (response.ok && response.json) {
ticket.customer_tier = response.json.tier;
ticket.lifetime_value = response.json.lifetime_value;

if (response.json.tier === "enterprise") {
ticket.priority = "High";
}
}

Exemplo: POST para webhook

var response = fetch("https://hooks.example.com/helpdesk", {
method: "POST",
body: { ticket_id: ticket.id, customer_email: ticket.customer.email }
});

Notas: Apenas HTTPS, timeout de 5s, limite de resposta de 1MB, redes internas bloqueadas.


Padroes Comuns​

Atribuicao Condicional​

// Definir prioridade com base no assunto
if (ticket.subject.toLowerCase().includes("urgent")) {
ticket.priority = "High";
} else if (ticket.subject.toLowerCase().includes("question")) {
ticket.priority = "Low";
}

Encaminhamento de Departamento​

var subject = ticket.subject.toLowerCase();

if (subject.includes("billing") || subject.includes("payment") || subject.includes("invoice")) {
ticket.department = "Billing";
} else if (subject.includes("technical") || subject.includes("bug") || subject.includes("error")) {
ticket.department = "Technical Support";
} else if (subject.includes("sales") || subject.includes("pricing") || subject.includes("quote")) {
ticket.department = "Sales";
}

Logica Baseada no Dominio do Cliente​

if (ticket.customer && ticket.customer.email) {
var email = ticket.customer.email;
var domain = email.split("@")[1];

// Tratamento de cliente enterprise
if (domain === "bigcorp.com" || domain === "enterprise.org") {
ticket.priority = "High";
ticket.department = "Enterprise Support";
ticket.is_enterprise = true;
}

// Instituicao educacional
if (domain.endsWith(".edu")) {
ticket.segment = "education";
}
}

Gestao de Tags​

// Adicionar tags sem perder as existentes
var existingTags = ticket.tags || [];
existingTags.push("processed");
existingTags.push("automated");
ticket.tags = existingTags;

Trabalhar com Mensagens​

if (message && message.body_text) {
var body = message.body_text.toLowerCase();

// Detetar palavras-chave de frustracao
var frustrationKeywords = ["frustrated", "angry", "terrible", "worst", "unacceptable"];
for (var i = 0; i < frustrationKeywords.length; i++) {
if (body.includes(frustrationKeywords[i])) {
ticket.priority = "High";
ticket.needs_attention = true;
break;
}
}
}

Atribuicao Round-Robin​

var users = getUsers();
if (users.length > 0) {
// Round-robin simples baseado em hash de ID do ticket
var ticketHash = 0;
for (var i = 0; i < ticket.id.length; i++) {
ticketHash += ticket.id.charCodeAt(i);
}
var assigneeIndex = ticketHash % users.length;
ticket.owner = users[assigneeIndex].email;
}

Tratamento de Erros​

Os scripts sao executados num ambiente seguro:

  • Erros de sintaxe sao capturados e registados; o script e ignorado.
  • Valores de campo invalidos (por exemplo, nome de estado inexistente) sao ignorados.
  • Timeouts (10 segundos) previnem loops infinitos.
  • Erros nao se propagam para outras regras ou componentes do sistema.

Melhores praticas:

// Verificar null/undefined antes de aceder a propriedades
if (ticket.customer && ticket.customer.email) {
// Seguro aceder a ticket.customer.email
}

if (message) {
// Seguro aceder a propriedades de message
}

// Usar try-catch para logica complexa
try {
var data = JSON.parse(ticket.custom_json);
ticket.parsed_field = data.value;
} catch (e) {
// Tratar erro graciosamente
}

Limitacoes​

  • Timeout de execucao: Os scripts sao terminados apos 10 segundos.
  • Sem acesso ao sistema de ficheiros: Operacoes de ficheiro nao estao disponiveis.
  • Sem estado persistente: As variaveis nao persistem entre execucoes de script.
  • Campos so de leitura: ticket.id, ticket.subject, ticket.customer nao podem ser modificados.
  • JavaScript ES5: Funcionalidades modernas de JavaScript (arrow functions, const/let, etc.) podem nao estar disponiveis.