---
name: fluig-scripts-avancados
description: Sub-processos, envio de e-mail, GED (documentos), notificacoes e operacoes avancadas no TOTVS Fluig. Use quando precisar iniciar sub-processos via hAPI, enviar e-mails com notifier, manipular documentos GED ou trabalhar com anexos de processo.
license: MIT
metadata:
  version: "1.0.0"
  author: Nevoa
  category: development
  platform: totvs-fluig
---

# Skill: fluig-scripts-avancados

> Sub-processos, envio de e-mail, GED (documentos), notificacoes e operacoes avancadas no TOTVS Fluig.

## Quando Usar

- Iniciar sub-processos via hAPI.startProcess()
- Enviar e-mails via notifier.notify()
- Criar/atualizar documentos no GED via Document WebService
- Buscar/mover anexos de processos
- Enviar notificacao para grupos de usuarios
- Operacoes com colleagueGroup (membros de grupo)

## 1. Sub-Processos (hAPI.startProcess)

### Uso em Eventos de Processo

```javascript
// Em qualquer evento de processo (afterTaskComplete, beforeStateEntry, etc.)
function initActivityPlanAction(posicao) {
    var PROCESSO_FILHO = "codigo_processo_filho";
    var userList = new java.util.ArrayList();
    var card = new java.util.HashMap();

    // Definir responsavel
    var responsavel = hAPI.getCardValue("matResponsavel");
    userList.add(responsavel);

    // Dados para o formulario do sub-processo
    card.put("campoFilho1", hAPI.getCardValue("campoPai1"));
    card.put("campoFilho2", hAPI.getCardValue("campoPai2"));
    card.put("nrProcessoPai", getValue("WKNumProces").toString());

    // Iniciar sub-processo
    hAPI.startProcess(
        PROCESSO_FILHO,   // codigo do processo
        0,                // atividade destino (0 = inicio)
        userList,         // responsaveis (java.util.ArrayList)
        "Iniciado automaticamente", // comentario
        true,             // completar tarefa
        card,             // dados do formulario (java.util.HashMap)
        true              // enviar como gestor
    );
}
```

### Evento subProcessCreated

```javascript
// Chamado APOS o sub-processo ser criado
function subProcessCreated(processId) {
    // processId = numero do sub-processo criado
    hAPI.setCardValue("nrSubProcesso", processId);
    log.info("=== Sub-processo criado: " + processId);
}
```

### Iniciar Processo via Dataset (WebService SOAP)

Ver template `dataset-soap-startprocess.js` na skill `fluig-integracoes`.

## 2. Envio de E-mail (notifier.notify)

### Padrao Basico

```javascript
// O template de e-mail deve estar cadastrado no Fluig
// Painel > Configuracoes > Templates de E-mail

var remetente = getValue("WKUser");
var parametros = new java.util.HashMap();
var destinatarios = new java.util.ArrayList();

// Parametros do template (substituem ${VARIAVEL} no HTML)
parametros.put("subject", "Assunto do E-mail");
parametros.put("SERVER_URL", "https://fluig.empresa.com.br");
parametros.put("mensagem", "Corpo da mensagem");
parametros.put("nrSolic", getValue("WKNumProces"));

// Destinatarios (login do usuario no Fluig)
destinatarios.add("login.usuario");

// Enviar
notifier.notify(
    remetente,        // string - login do remetente
    "templateEmail",  // string - codigo do template
    parametros,       // java.util.HashMap - parametros do template
    destinatarios,    // java.util.ArrayList - logins dos destinatarios
    "text/html"       // string - tipo do conteudo
);
```

### Enviar para Grupo Inteiro

```javascript
// Buscar membros do grupo
var c1 = DatasetFactory.createConstraint(
    "colleagueGroupPK.groupId", "NomeGrupo", "NomeGrupo", ConstraintType.MUST);
var dsGrupo = DatasetFactory.getDataset("colleagueGroup", null, new Array(c1), null);

var destinatarios = new java.util.ArrayList();
for (var i = 0; i < dsGrupo.rowsCount; i++) {
    destinatarios.add(dsGrupo.getValue(i, "colleagueGroupPK.colleagueId"));
}

notifier.notify(remetente, "templateEmail", parametros, destinatarios, "text/html");
```

### Buscar E-mail e Enviar por E-mail

```javascript
// Buscar usuario pelo e-mail
var c1 = DatasetFactory.createConstraint("mail", email, email, ConstraintType.MUST);
var ds = DatasetFactory.getDataset("colleague", null, new Array(c1), null);
var login = ds.getValue(0, "colleaguePK.colleagueId");
var nome = ds.getValue(0, "colleagueName");

// Montar destinatarios dinamicamente
var destinatarios = new java.util.ArrayList();
var emails = hAPI.getCardValue("emailsNotificacao"); // campo com "email1;email2;email3"
var aux = emails.trim().split(";");
for (var i = 0; i < aux.length; i++) {
    var c1 = DatasetFactory.createConstraint("mail", aux[i], aux[i], ConstraintType.MUST);
    var ds = DatasetFactory.getDataset("colleague", null, new Array(c1), null);
    if (ds.rowsCount > 0) {
        destinatarios.add(ds.getValue(0, "colleaguePK.colleagueId"));
    }
}
```

### Enviar com Link para o Processo

```javascript
parametros.put("LINK",
    "https://fluig.empresa.com.br/portal/p/1/pageworkflowview" +
    "?app_ecm_workflowview_detailsProcessInstanceID=" + getValue("WKNumProces"));
```

## 3. GED - Gestao de Documentos

### Obter Servico de Documentos

```javascript
var documentServiceProvider = ServiceManager.getServiceInstance("Document");
var documentServiceLocator = documentServiceProvider.instantiate(
    "com.datasul.technology.webdesk.dm.ws.DocumentServiceService");
var documentService = documentServiceLocator.getDocumentServicePort();
```

### Buscar Documento por ID

```javascript
var document = documentService.getDocumentVersion(
    usuario,                    // login
    senha,                      // "MD5:" + hash ou senha
    getValue("WKCompany"),      // empresa
    documentId,                 // ID do documento
    versao,                     // versao (1000 = primeira)
    getValue("WKUser"));        // usuario solicitante

var doc = document.getItem().get(0);
var nomeArquivo = doc.getPhisicalFile();
var descricao = doc.getDocumentDescription();
```

### Criar Documento no GED

```javascript
// Configurar documento
doc.setDocumentDescription("Nome do documento");
doc.setParentDocumentId(new java.lang.Integer(idPasta));
doc.setColleagueId(getValue("WKUser"));
doc.setCompanyId(getValue("WKCompany"));
doc.setDocumentType("2");           // 2 = documento
doc.setTopicId(new java.lang.Integer(3));
doc.setInheritSecurity(true);
doc.setActiveVersion(true);
doc.setApproved(true);
doc.setVolumeId("Default");
doc.setDocumentId(0);              // 0 = novo documento

// Anexar arquivo
var attach = documentServiceProvider.instantiate(
    "com.datasul.technology.webdesk.dm.ws.Attachment");
attach.setFileName(nomeArquivo);
attach.setFilecontent(conteudoBytes);
attach.setPrincipal(true);
attach.setEditing(false);

var attachArray = documentServiceProvider.instantiate(
    "com.datasul.technology.webdesk.dm.ws.AttachmentArray");
attachArray.getItem().add(attach);

// Seguranca e aprovadores
var docSec = documentServiceProvider.instantiate(
    "com.datasul.technology.webdesk.dm.ws.DocumentSecurityConfigDtoArray");
var aprovDoc = documentServiceProvider.instantiate(
    "com.datasul.technology.webdesk.dm.ws.ApproverDtoArray");
var relatedArr = documentServiceProvider.instantiate(
    "com.datasul.technology.webdesk.dm.ws.RelatedDocumentDtoArray");

// Criar
var resultado = documentService.createDocument(
    usuario, senha, getValue("WKCompany"),
    document, attachArray, docSec, aprovDoc, relatedArr);

var wsm = resultado.getItem().get(0);
if (wsm.getWebServiceMessage() != "ok") {
    throw "ERRO: " + wsm.getWebServiceMessage();
}
```

### Mover Documento

```javascript
var wep = ServiceManager.getServiceInstance("Document");
var lista_docs = wep.instantiate("net.java.dev.jaxb.array.IntArray");
lista_docs.getItem().add(new java.lang.Integer(documentId));

documentService.moveDocument(
    usuario, senha, getValue("WKCompany"),
    lista_docs,
    getValue("WKUser"),
    idPastaDestino);
```

### Buscar Anexos do Processo

```javascript
var c1 = DatasetFactory.createConstraint(
    "processAttachmentPK.processInstanceId",
    getValue("WKNumProces"), getValue("WKNumProces"), ConstraintType.MUST);
var c2 = DatasetFactory.createConstraint(
    "processAttachmentPK.companyId",
    getValue("WKCompany"), getValue("WKCompany"), ConstraintType.MUST);

var attachDataset = DatasetFactory.getDataset(
    "processAttachment",
    new Array("documentId", "processAttachmentPK.attachmentSequence", "version"),
    new Array(c1, c2),
    new Array("processAttachmentPK.attachmentSequence"));

for (var i = 0; i < attachDataset.rowsCount; i++) {
    var docId = attachDataset.getValue(i, "documentId");
    var versao = attachDataset.getValue(i, "version");
}
```

### Buscar Documentos Relacionados

```javascript
var buscaRel = documentService.getRelatedDocuments(
    usuario, senha, getValue("WKCompany"), documentId, versao);

if (buscaRel != null) {
    for (var i = 0; i < buscaRel.getItem().size(); i++) {
        var docRel = buscaRel.getItem().get(i);
        var relatedDocId = docRel.relatedDocumentId;
        var relatedVersion = docRel.version;
    }
}
```

## 4. Criar Pasta no GED

```javascript
function createFolder(idPastaPai, nomePasta) {
    var documentServiceProvider = ServiceManager.getServiceInstance("Document");
    var documentServiceLocator = documentServiceProvider.instantiate(
        "com.datasul.technology.webdesk.dm.ws.DocumentServiceService");
    var documentService = documentServiceLocator.getDocumentServicePort();

    var docArray = documentServiceProvider.instantiate(
        "com.datasul.technology.webdesk.dm.ws.DocumentDtoArray");
    var doc = documentServiceProvider.instantiate(
        "com.datasul.technology.webdesk.dm.ws.DocumentDto");

    doc.setDocumentDescription(nomePasta);
    doc.setDocumentType("1");                    // 1 = pasta
    doc.setParentDocumentId(new java.lang.Integer(idPastaPai));
    doc.setInheritSecurity(true);
    doc.setVolumeId("Default");
    doc.setCompanyId(getValue("WKCompany"));
    doc.setColleagueId(getValue("WKUser"));

    docArray.getItem().add(doc);

    var attachArray = documentServiceProvider.instantiate(
        "com.datasul.technology.webdesk.dm.ws.AttachmentArray");
    var docSec = documentServiceProvider.instantiate(
        "com.datasul.technology.webdesk.dm.ws.DocumentSecurityConfigDtoArray");
    var aprovDoc = documentServiceProvider.instantiate(
        "com.datasul.technology.webdesk.dm.ws.ApproverDtoArray");
    var relatedArr = documentServiceProvider.instantiate(
        "com.datasul.technology.webdesk.dm.ws.RelatedDocumentDtoArray");

    var resultado = documentService.createDocument(
        usuario, senha, getValue("WKCompany"),
        docArray, attachArray, docSec, aprovDoc, relatedArr);

    return resultado.getItem().get(0).getDocumentId();
}
```

## 5. Datasets Internos Uteis

Datasets built-in: `colleague`, `colleagueGroup`, `workflowProcess`, `processAttachment`, `processHistory`, `processTask`, `processState`, `document`.

> Tabela completa com campos e exemplos: [references/datasets-internos-e-hapi.md](./references/datasets-internos-e-hapi.md)

## Checklist de Producao

- [ ] Sub-processo: userList como java.util.ArrayList, card como java.util.HashMap
- [ ] E-mail: template cadastrado no Painel do Fluig
- [ ] E-mail: destinatarios sao LOGINS (nao e-mails)
- [ ] GED: senha com prefixo "MD5:" quando usar hash
- [ ] GED: fechar conexoes em finally
- [ ] GED: tratar retorno getWebServiceMessage() != "ok"
- [ ] Anexos: usar dataset processAttachment para listar
- [ ] Grupos: dataset colleagueGroup para buscar membros
- [ ] try/catch em todas as operacoes
- [ ] log.info para rastreabilidade

## Prompts Estrategicos Disponiveis

- `orquestrar-subprocessos-hapi-startprocess.md` - Orquestracao de subprocessos via `hAPI.startProcess`.
- `implementar-motor-notificacao-notifier.md` - Motor de notificacao com `notifier.notify`.
- `implementar-gestao-ged-anexos-processo.md` - GED e anexos de processo com `Document` WebService.
- `diagnosticar-falhas-scripts-avancados-recuperacao.md` - Diagnostico e recuperacao de falhas em scripts avancados.

Use estes prompts para operacoes avancadas de workflow/ECM com foco em robustez operacional.
## Skills Relacionadas

- [fluig-eventos-processo](../fluig-eventos-processo/SKILL.md) — Eventos de workflow onde scripts avancados sao chamados
- [fluig-integracoes](../fluig-integracoes/SKILL.md) — REST/SOAP para integracao com ERP
- [fluig-datasets](../fluig-datasets/SKILL.md) — Datasets internos (colleague, processAttachment)

## Templates Disponiveis

| Template | Descricao |
|---|---|
| `subprocesso-hapi.js` | Iniciar sub-processo via hAPI.startProcess() |
| `notificacao-email.js` | Envio de e-mail com notifier.notify() + grupo |
| `ged-document-service.js` | Criar/atualizar documentos no GED |
| `ged-anexos-processo.js` | Buscar e manipular anexos de processos |

## Recursos Adicionais

- Para templates base, consulte [templates/](./templates/)
- Para exemplos de implementacao real, consulte [examples/](./examples/)
### Exemplos recomendados
- [exemplo_01_subprocesso_em_lote_wf0035_afterTaskComplete](./examples/exemplo_01_subprocesso_em_lote_wf0035_afterTaskComplete/): `afterTaskComplete` com subprocesso em lote e helpers de prazo/data.
- [exemplo_02_helper_notifier_notify_fnEnviarMail](./examples/exemplo_02_helper_notifier_notify_fnEnviarMail/): helper reutilizavel para notificacao com `notifier.notify`.
- Para referencia de datasets internos e hAPI, consulte [references/datasets-internos-e-hapi.md](./references/datasets-internos-e-hapi.md)
- Para prompts de uso, consulte [prompts/](./prompts/)

---

## Curadoria de Contexto Local

Para buscar exemplos reais no acervo local `Contexto`, consulte [references/contexto-curadoria.md](./references/contexto-curadoria.md).
Abra essa referencia quando a tarefa exigir aderencia a legado/producao ou comparacao com implementacoes existentes.
