As propriedades de extensão contêm informações especiais que podem alterar o comportamento padrão do processo em algum ponto. Elas devem ser utilizadas principalmente durante a fase de customização ou conter "flags" especiais que alterem alguma lógica interna (apenas em casos especiais).
O cadastro de propriedades de extensão do processo é realizado pelo Fluig Studio, sendo necessário que o diagrama do processo já esteja criado. Para cadastrar um novo atributo, é necessário abrir o processo para edição e na visão 'Properties' acessar a aba Extensão:
Deve-se utilizar os botões Adicionar novo Atributo, para adicionar uma propriedade de extensão. Abaixo o formulário para a criação de um novo atributo.
Neste exemplo iremos criar atividades automáticas customizadas.
Na imagem a seguir é possível visualizar o atributo adicionado, definindo as atividades 2 e 4 (separadas por vírgula) como atividades automáticas do processo.
Os eventos de um processo são um conjunto de scripts carregados pela API de workflow. Tais scripts são desenvolvidos com o uso da linguagem JavaScript e chamados ao longo da execução do processo em momentos pré-determinados, como por exemplo a criação da solicitação do processo ou a entrada em uma nova atividade.
A implementação dos eventos do processo é realizada pelo Fluig Studio, sendo necessário já existir um projeto Fluig com pelo menos um diagrama de processo.
Para criar um novo evento do processo, clicar com o botão direito do mouse no projeto, acessar a opção New e em seguida a opção Other. No assistente aberto, selecionar a opção "Script Evento Workflow", presente na pasta Fluig, e clicar no botão Next. Na nova tela selecionar qual o evento que será criado e relacionar ele a um processo já existente. Para finalizar, clicar no botão Finish:
A partir do Fluig 1.4.9, é possível acompanhar a execução dos eventos através do novo componente loading. Com este acompanhamento, é possível apresentar mensagens para o usuário tomar conhecimento das rotinas que estão sendo executadas quando a solicitação é encaminhada para a próxima atividade. Essa ferramenta também pode ser muito útil para o desenvolvedor identificar pontos de baixa performance nos desenvolvimentos realizados sob a plataforma.
Para a utilização desta funcionalidade, basta utilizar o trecho loading.setMessage(String message) na implementação do evento, conforme exemplo no trecho de código abaixo:
function validateForm(form){ loading.setMessage("Validando campos de formulário"); if(form.getValue('nome') == null || form.getValue('nome') == '') { throw "Campo nome não está preenchido"; } loading.setMessage(""); } |
Assim, durante a execução deste evento, a mensagem definida na implementação do mesmo aparecerá na tela para o usuário acompanhar, conforme imagem abaixo:
|
Em todos os eventos do processo é possível obter informações da API de Workflow. Cada evento possui acesso ao handle da API de workflow através da variável global hAPI. Os seguintes métodos estão disponíveis através da hAPI:
Método | Especificação | ||
---|---|---|---|
getCardValue("nomeCampo") | Permite acessar o valor de um campo do formulário do processo, onde:
| ||
setCardValue("nomeCampo", "valor") | Permite definir o valor de um campo do formulário do processo, onde:
| ||
setAutomaticDecision(numAtiv, listaColab, "obs") | Permite definir o fluxo de saída de uma atividade de forma automática, onde:
| ||
getActiveStates() | Retorna uma lista das atividades ativas do processo. | ||
getActualThread(numEmpresa, numProcesso, numAtiv) | Retorna a thread da atividade que está ativa, lembrando que em caso de atividades paralelas, retorna 0, 1, 2 e assim sucessivamente.
Exemplo de uso para esta função:
| ||
setDueDate(numProcesso, numThread, "userId", dataConclusao, tempoSeg) | Permite alterar o prazo de conclusão para uma determinada atividade do processo, onde:
| ||
transferTask(transferUsers, "obs", int numThread) | Transfere uma tarefa de um usuário para outro(s) usuário(s).
| ||
transferTask(transferUsers, "obs") | Transfere uma tarefa de um usuário para outro(s) usuário(s). Este método não pode ser usado em processos com atividades paralelas:
| ||
startProcess(processId, ativDest, listaColab, "obs", completarTarefa, valoresForm, modoGestor) | Inicia uma solicitação workflow, onde:
Retorna um mapa com informações da solicitação criada. Entre elas, o iProcess que é o número da solicitação criada. | ||
setColleagueReplacement(userId) | Seta um usuário substituto, onde:
| ||
setTaskComments("userId", numProcesso, numThread, "obs") | Define uma observação para uma determinada tarefa do processo, onde:
| ||
getCardData(numProcesso) | Retorna um Mapa com todos os campos e valores do formulário da solicitação.
| ||
getAdvancedProperty("propriedade") | Retorna o valor da propriedade avançada de um processo.
| ||
calculateDeadLineHours(data, segundos, prazo, periodId) | Calcula um prazo a partir de uma data com base no expediente e feriados cadastrados no produto passando o prazo em horas:
Retorno: Array de Objeto, onde a primeira posição do array é a data e a segunda a hora. Exemplo:
| ||
calculateDeadLineTime(data, segundos, prazo, periodId) | Calcula um prazo a partir de uma data com base no expediente e feriados cadastrados no produto passando o prazo em minutos:
Retorno: Array de Objeto, onde a primeira posição do array é a data e a segunda a hora. Exemplo:
| ||
getUserTaskLink(numAtiv) | Permite buscar o link para movimentação de uma determinada atividade, e utilizá-lo para enviar um e-mail com template customizado, por exemplo.
Retorno: link para movimentação da solicitação.
Exemplo:
| ||
createAdHocTasks(workflowProcessInstanceId, sequenceId, assunto, detalhamento, listatvidadesAhoc) | Permite a criação de atividades adhoc dentro dos eventos do Fluig
Exemplo:
| ||
listAttachments() | Retorna a lista de anexos do processo.
| ||
publishWorkflowAttachment(documento) | Permite publicar anexos workflow da solicitação no GED do Fluig, onde:
Exemplo:
| ||
attachDocument(documentId) | Permite anexar documentos do GED a solicitação workflow, onde:
Exemplo:
| ||
getAvailableStatesDetail(companyId, userId, processId, processInstanceId, threadSequence) | Retorna detalhes das atividades disponíveis para seleção.
Parâmetros:
Retorno: ProcessStateDto[]. | ||
getChildrenInstances(processInstanceId) | Retorna uma lista com os números das solicitações filhas, onde:
Exemplo:
| ||
getParentInstance(processInstanceId) | Retorna o número da solicitação pai, onde:
Exemplo:
| ||
addCardChild(tableName, cardData) | Adiciona um filho no formulário pai e filho do processo, onde:
Exemplo:
|
Nos eventos existe a possibilidade de integração com serviços de dados. Tais serviços podem ser WebServices, AppServer Progress® e Dataset.
O acesso a WebServices ou AppServer Progress® deve ser previamente configurado no cadastro de Serviços. Para mais detalhes consulte em Integração Com Aplicativos Externos, no capítulo "Acessando WebServices a partir do Fluig".
Abaixo um exemplo de como executar o WebService de Colleague para criar um usuário no Fluig após executar uma tarefa:
function afterTaskComplete(colleagueId, nextSequenceId, userList) { if (nextSequenceId == 2) { //Busca o webservices de Colaborador var colleagueServiceProvider = ServiceManager.getServiceInstance("Colleague"); var colleagueServiceLocator = colleagueServiceProvider.instantiate("com.totvs.technology.ecm.foundation.ws.ECMColleagueServiceService"); var colleagueService = colleagueServiceLocator.getColleagueServicePort(); //Cria o ColleagueDto – Verificar a lista de métodos na visualização do serviço var colleagueDto = colleagueServiceProvider.instantiate("com.totvs.technology.ecm.foundation.ws.ColleagueDto"); colleagueDto.setCompanyId(1); colleagueDto.setColleagueId("teste"); colleagueDto.setColleagueName("Usuario Teste"); colleagueDto.setActive(true); colleagueDto.setVolumeId("Default"); colleagueDto.setLogin("teste"); colleagueDto.setMail("[email protected]"); colleagueDto.setPasswd("teste"); colleagueDto.setAdminUser(false); colleagueDto.setEmailHtml(true); colleagueDto.setDialectId("pt_BR"); //Cria o colleagueDtoArray e adiciona var colleagueDtoArray = colleagueServiceProvider.instantiate("com.totvs.technology.ecm.foundation.ws.ColleagueDtoArray"); colleagueDtoArray.getItem().add(colleagueDto); var result = colleagueService.createColleague("adm", "adm", 1, colleagueDtoArray); log.info("Result: " + result); } } |
Abaixo um outro exemplo utilizando o WebService ECMCardService para alterar o valor do campo de um registro de formulário após a entrada em uma nova atividade:
function afterStateEntry(sequenceId){ if (nextSequenceId == 2) { //Servico "<url_fluig>/webdesk/ECMCardService?wsdl"cadastrado com o código "CardService" var cardServiceProvider = ServiceManager.getServiceInstance("CardService"); var cardServiceLocator = cardServiceProvider.instantiate("com.totvs.technology.ecm.dm.ws.ECMCardServiceServiceLocator"); var cardService = cardServiceLocator.getCardServicePort(); var cardFieldDtoArray = cardServiceProvider.instantiate("com.totvs.technology.ecm.dm.ws.CardFieldDtoArray"); var cardField = cardServiceProvider.instantiate("com.totvs.technology.ecm.dm.ws.CardFieldDto"); //Seta valor no campo com name = 'nome' cardField.setField("nome"); cardField.setValue("Valor alterado via WS dentro de um evento workflow"); var vetCardFields = new Array(); cardFieldDtoArray.setItem(vetCardFields.push(cardField)); //Altera o(s) campo(s) da ficha. cardService.updateCardData(1, "adm", "adm", 8, cardFieldDtoArray); } } |
Os seguintes eventos são disparados pela API de Workflow:
Evento | Descrição | Parâmetros | |
---|---|---|---|
afterCancelProcess | Ocorre após o cancelamento da solicitação. É recomendado não disparar exceções neste método, pois o cancelamento já foi realizado. |
| |
afterProcessCreate | Ocorre logo após a criação de um novo processo.
|
| |
afterProcessFinish | Ocorre após finalizada a solicitação. |
| |
afterReleaseVersion | Ocorre após a liberação de uma versão do processo. |
| |
afterStateEntry | Ocorre após a entrada em uma nova atividade. |
| |
afterStateLeave | Ocorre após a saída de uma atividade. |
| |
afterTaskComplete | Ocorre após o usuário completar uma tarefa, porém as informações de próxima tarefa e usuários destino já foram salvas. |
| |
afterTaskCreate | Ocorre após o usuário receber uma tarefa. |
| |
afterTaskSave | Ocorre após salvar as informações selecionadas pelo usuário. |
| |
beforeCancelProcess | Ocorre antes do cancelamento da solicitação. |
| |
beforeStateEntry | Ocorre antes da entrada em uma nova atividade. |
| |
beforeStateLeave | Ocorre antes da saída de uma atividade. |
| |
beforeTaskComplete | Ocorre antes que o usuário complete uma tarefa, porém as informações de próxima tarefa e usuários destino já foram salvas. |
| |
beforeTaskCreate | Ocorre antes que o usuário receba uma tarefa. |
| |
beforeTaskSave | Ocorre antes de salvar as informações selecionadas pelo usuário. |
| |
calculateAgreement | Ocorre após o cálculo do consenso (somente para atividades conjuntas) e permite alterar os dados do consenso de uma atividade. Exemplo:
|
| |
onNotify | Se refere a um evento global que ocorre após a movimentação da solicitação e antes de enviar as notificações. | Para mais detalhes consulte a página Desenvolvimento de Eventos - On Notify. | |
setProcess | Ocorre quando um processo é "setado" na API.
|
| |
subProcessCreated | Ocorre quando um sub-processo é criado. |
| |
validateAvailableStates | Ocorre após montada a lista de tarefas disponíveis para o usuário a partir da tarefa atual. |
|
|
Importante: Não é possível capturar (hAPI.getCardValue) ou adicionar (hAPI.setCardValue) dados no formulário na inicialização do processo, sendo possível somente a partir da segunda tarefa. Para isso pode ser utilizado a seguinte lógica:
|
Com o uso de eventos, o Fluig permite que um processo seja customizado possibilitando a execução de ações definidas pelo usuário, tais como:
Existem algumas propriedades que contém informações referentes à solicitação que podem ser utilizadas na customização do processo, são elas:
Parâmetro | Descrição |
---|---|
WKDef | Código do processo |
WKVersDef | Versão do processo |
WKNumProces | Número da solicitação de processo |
WKNumState | Número da atividade |
WKCompany | Número da empresa |
WKUser | Código do usuário corrente |
WKUserComment | Comentário feito pelo usuário na atividade ou no cancelamento da solicitação |
WKCompletTask | Se a tarefa foi completada (true/false) |
WKNextState | Número da próxima atividade (destino) |
WKCardId | Código do formulário do processo |
WKFormId | Código da definição de formulário do processo |
WKIdentityCompany | Identificador da Empresa selecionada para Experiências de uso TOTVS |
WKMobile | Identifica se a ação foi realizada através de um dispositivo mobile. |
WKIsService | Identifica se a solicitação de cancelamento foi realizada através de um serviço. Esta variável só poderá ser consultada nos eventos beforeCancelProcess e afterCancelProcess. |
WKUserLocale | Identifica o idioma corrente do usuário. |
Além dessas propriedades já alimentadas pelo produto, é possível criar propriedades customizadas que podem ser utilizadas nos eventos. O produto disponibiliza a variável globalVars, que é um mapa de dados (Map<String, String>) e estará disponível em todos os eventos.
Para adicionar uma propriedade e seu valor, utilize o método globalVars.put("name", "value"), onde "name" é o nome da propriedade e "value" o seu valor. Exemplo: globalVars.put("WDAprovador","adm");
Para recuperar os valores da variável globalVars, utilize o método globalVars.get("name"), onde "name" é o nome da propriedade a ser retornado o valor. Exemplo: globalVars.get("WDAprovador");
|
As exceções podem ser tratadas nos seguintes eventos: beforeStateEntry, beforeTaskSave e beforeCancelProcess. O tratamento de exceção no evento beforeStateEntry pode ser utilizado na inicialização de solicitações, pois ele impede que a solicitação seja iniciada. O tratamento de exceção no evento beforeTaskSave pode ser utilizado somente se a solicitação já estiver inicializada.
Abaixo é apresentado os modelos para utilização em cada um dos eventos:
function beforeStateEntry(sequenceId) { var activity = getValue("WKNumState"); if (activity == 0 || activity == 1) { //Outra condição. throw "TRATAMENTO DE EXCEÇÃO"; } } function beforeTaskSave(colleagueId, nextSequenceId, userList) { var activity = getValue("WKNumState"); if (activity != 0 && activity != 1) { //Outra condição throw "TRATAMENTO DE EXCEÇÃO"; } } function beforeCancelProcess(colleagueId, processId) { //Condição. throw "TRATAMENTO DE EXCEÇÃO"; } |
É possível consultar o campo observação de uma solicitação de processo, verificando se ele foi preenchido ou não. Para isto, é necessário validar a propriedade WKUserComment no evento beforeTaskSave ou no evento beforeCancelProcess. Exemplo:
function beforeTaskSave(colleagueId, nextSequenceId, userList) { if (getValue("WKUserComment") == null || getValue("WKUserComment") == "") { throw "A observação deve ser preenchida"; } } function beforeCancelProcess(colleagueId, processId) { if (getValue("WKUserComment") == null || getValue("WKUserComment") == "") { throw "A observação deve ser preenchida"; } } |
Os mecanismos de atribuição são instrumentos utilizados durante um processo de workflow que permitem criar, segundo um critério estabelecido pelo próprio mecanismo, uma lista de possíveis usuários para uma atividade. Esta lista pode ser utilizada em dois momentos:
No primeiro caso, a lista é gerada de acordo com o mecanismo de atribuição existente na primeira atividade do processo (que representa a atividade inicial). Nas demais atividades é adotado o segundo procedimento. Quando não houver um mecanismo de atribuição associado a uma atividade (seja ela inicial ou não), todos os usuários são considerados válidos.
O Fluig possui alguns mecanismos de atribuição padrões, conforme abaixo:
Mecanismo de Atribuição | Descrição |
---|---|
Para um Papel (Pool) | Permite atribuir tarefas a um papel e não apenas a um usuário. Assim, qualquer um dos usuários neste papel pode assumir as tarefas para completá-las. |
Para um Grupo (Pool) | Permite atribuir tarefas a um grupo e não apenas a um usuário. Assim, qualquer um dos usuários deste grupo pode assumir as tarefas para completá-las. |
Por Associação | Permite compor lógicas complexas de atribuição por intermédio da associação de vários mecanismos. |
Por Campo de Formulário | Permite atribuir tarefas ao usuário informado em um campo do formulário do processo. |
Por Executor de Atividade | Permite selecionar os usuários que executaram uma atividade anterior. |
Por Grupo | Permite filtrar apenas os usuários que façam parte de um determinado grupo. |
Por Grupos do Usuário | Permite filtrar apenas os usuários que pertençam a um dos grupos do usuário corrente, ou do usuário que iniciou o processo (solicitante). Também permite filtrar apenas os usuários cujo grupo de trabalho seja o mesmo do usuário (corrente ou solicitante). |
Por Papel | Permite filtrar apenas os usuários que possuam um determinado papel. |
Por Usuário | Permite atribuir tarefas a um usuário específico. |
A criação de um mecanismo de atribuição é realizada pelo Fluig Studio, sendo necessário já existir um projeto Fluig.
Utilize o passo-a-passo para conhecer o processo de criação de um mecanismo de atribuição de exemplo:
|
Para processos que possuem uma definição de formulário definida são passados alguns parâmetros com informações sobre o processo para serem utilizados nos eventos da definição de formulário, conforme abaixo:
Parâmetro | Descrição |
---|---|
WKDef | Código do processo |
WKVersDef | Versão do processo |
WKNumProces | Número da solicitação de processo |
WKNumState | Número da atividade movimentada |
WKCurrentState | Número da atividade atual |
WKCompany | Número da empresa |
WKUser | Código do usuário corrente |
WKCompletTask | Se a tarefa foi completada (true/false) |
WKNextState | Número da próxima atividade (destino) |
WKCardId | Código do formulário do processo |
WKFormId | Código da definição de formulário do processo |
WKIdentityCompany | Identificador da Empresa selecionada para Experiências de uso TOTVS |
Nos scripts dos eventos da definição de formulário basta recuperar as informações com o comando getValue, conforme exemplo:
var vCodProcess = getValue("WKDef"); |
Sobre customizações de notificações e e-mail, acompanhe informações detalhadas em:
|