Files
2026-09-23 12:29:08 -03:00

167 lines
5.2 KiB
Markdown

# Processes
BPMN workflows powered by Activiti. Each process lives in its own subdirectory.
```
processes/
<process-key>/
<process-key>.bpmn
<process-key>-desktop.xml
<process-key>-mobile.xml # optional when process involves mobile tasks.
<process-key>-mobile-alt.xml # optional when the client uses two versions of the mobile with different APIs. User should point the need for that one out.
```
The XML form rules, components, engine API, and JS constraints are the same as panels — see `panels/CLAUDE.md`. This file covers only the differences.
---
## vitruvio.json registration
```json
"processes": [
{
"key": "my-process",
"name": "My Process",
"bpmn": "processes/my-process/my-process.bpmn",
"forms": {
"desktop": "processes/my-process/my-process-desktop.xml",
"mobile": null,
"mobileAlternative": null
},
"schedules": [
{
"name": "Daily trigger",
"trigger": { "type": "cron", "expression": "0 0 0 * * ?" }
}
]
}
]
```
`schedules` is optional. Trigger types: `"cron"` (Quartz expression) or `"simple"` (`intervalMs` + `repeatCount: -1` for indefinite).
---
## Form XML — key differences from panels
The root element is `<forms>` (not `<form>`), with a `processKey` attribute matching the BPMN process id:
```xml
<forms xmlns="http://www.davinti.com.br/vitruvio/form"
xmlns:xsi="..."
xsi:schemaLocation="..."
processKey="my-process">
<library>
<!-- reusable complex-component definitions -->
</library>
<form formKey="formAbertura" width="100%">
<!-- components for the start event / opening task -->
</form>
<form formKey="formAprovacao" width="100%">
<!-- components for approval task -->
</form>
</forms>
```
### `<library>`
Define reusable `<complex-component>` blocks here and reference them by id in task forms. Avoids repeating the same layout across multiple task forms.
### `<form formKey="...">`
Each `<form>` corresponds to one BPMN user task (via `activiti:formKey`). The keys must match exactly. One process can have many task forms in the same XML file.
---
## BPMN — key attributes
### User tasks
```xml
<bpmn2:userTask id="Task_Approve" name="Approve"
activiti:formKey="formAprovacao"
activiti:candidateGroups="group-key"
activiti:assignee="${someVar}">
```
- `activiti:formKey` — must match a `<form formKey="...">` in the desktop/mobile XML.
- `activiti:candidateGroups` — group key(s) that can claim this task.
- `activiti:assignee` — specific user expression (optional, overrides candidate groups).
### Start event
```xml
<bpmn2:startEvent id="start" activiti:formKey="formAbertura" activiti:initiator="owner">
```
`activiti:initiator="owner"` stores the login of whoever opened the process into the `owner` process variable.
### Sequence flow conditions
Conditions reference process variables using JUEL syntax:
```xml
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">
#{formAbertura_aprovado=='1'}
</bpmn2:conditionExpression>
```
Process variables are set by the form engine automatically following the convention `{formKey}_{fieldId}` when a task is completed. They can also be set explicitly in script tasks via the `execution` object.
### Script tasks
```xml
<bpmn2:scriptTask id="myScript" name="Do something" scriptFormat="javascript">
<bpmn2:script>
var lib = vScriptService.loadScript('my-lib', 'javascript');
var obj = new lib.MyClass();
obj.doWork(execution);
</bpmn2:script>
</bpmn2:scriptTask>
```
- Use `vScriptService.loadScript(key, 'javascript')` — **not** `libService.loadScript()`.
- `execution` is the Activiti execution context. Use it to read/write process variables:
```javascript
execution.getVariable('myVar');
execution.setVariable('myVar', value);
```
### Task listeners
Listeners run on task lifecycle events (`create`, `complete`, `assignment`):
```xml
<activiti:taskListener class="org.activiti.engine.impl.bpmn.listener.ScriptTaskListener" event="create">
<activiti:field name="language"><activiti:string>javascript</activiti:string></activiti:field>
<activiti:field name="script">
<activiti:string>
var lib = vScriptService.loadScript('my-lib', 'javascript');
lib.onTaskCreate(task);
</activiti:string>
</activiti:field>
</activiti:taskListener>
```
`task` is available in listeners (not `execution`). Use `task.getExecution()` if you need the execution context.
---
## Engine extras in process forms
These are available in addition to the standard panel engine API:
| Method | Description |
| ------------------------- | ---------------------------------------------------------------------- |
| `engine.formKey()` | Returns the `formKey` of the currently active task form |
| `engine.isTaskComplete()` | Returns `true` if the task has already been completed (read-only view) |
Use `engine.formKey()` to share `initScript` logic across multiple task forms with different initialization paths:
```javascript
function run() {
if (engine.formKey() == 'formAbertura') {
// init for opening form
} else if (engine.formKey() == 'formAprovacao') {
// init for approval form
}
}
```