Skip to content

Commit

Permalink
Feature/tasklist support custom fields (#415)
Browse files Browse the repository at this point in the history
closes #406 

**Changes**

- Taskvariables named in a specific pattern (e.g. `miranum_task_***` are
automatically added to miranum tasklist as custom fields
- The prefix for variables is customizable (default `miranum_task_`)
  • Loading branch information
lmoesle authored Jul 15, 2024
1 parent a882f3c commit 40bd230
Show file tree
Hide file tree
Showing 22 changed files with 461 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .run/MiranumPlatformSDU.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<module name="miranum-single-deployment-unit-example" />
<option name="SPRING_BOOT_MAIN_CLASS" value="io.miragon.miranum.platform.example.MiranumPlatformSDU" />
<extension name="net.ashald.envfile">
<option name="IS_ENABLED" value="false" />
<option name="IS_ENABLED" value="true" />
<option name="IS_SUBST" value="false" />
<option name="IS_PATH_MACRO_SUPPORTED" value="false" />
<option name="IS_IGNORE_MISSING_FILES" value="false" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<bpmn:userTask id="Activity_12rgiry" name="Check Resources" camunda:modelerTemplate="io.miranum.basis-usertask">
<bpmn:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="app_task_description" />
<camunda:inputParameter name="app_task_form" />
<camunda:inputParameter name="miranum_task_form">check-resources</camunda:inputParameter>
<camunda:inputParameter name="miranum_task_description">Überprüfe Kapazität</camunda:inputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0mci6qe</bpmn:incoming>
Expand All @@ -32,8 +32,8 @@
<bpmn:userTask id="Activity_0iahoe8" name="Create Offer" camunda:modelerTemplate="io.miranum.basis-usertask">
<bpmn:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="app_task_description" />
<camunda:inputParameter name="app_task_form" />
<camunda:inputParameter name="miranum_task_form">create-offer</camunda:inputParameter>
<camunda:inputParameter name="miranum_task_description">Create an offer based on inquiry</camunda:inputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0gbm3j2</bpmn:incoming>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"type": "Text",
"binding": {
"type": "camunda:inputParameter",
"name": "app_task_description"
"name": "miranum_task_description"
}
},
{
Expand All @@ -47,7 +47,7 @@
"type": "String",
"binding": {
"type": "camunda:inputParameter",
"name": "app_task_form"
"name": "miranum_task_form"
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ camunda:
enable-exceptions-after-unhandled-bpmn-error: true
database:
schema-update: false
auto-deployment-enabled: false
auto-deployment-enabled: true
admin-user:
id: ${CAMUNDA_COCKPIT_USERNAME:demo}
password: ${CAMUNDA_COCKPIT_PASSWORD:demo}
Expand All @@ -31,6 +31,7 @@ camunda:
metrics:
enabled: false
db-reporter-activate: false
deployment-resource-pattern: "processes/*.bpmn"

management:
server:
Expand Down Expand Up @@ -136,3 +137,5 @@ miranum:
tasklist:
# if you want to disable the tasklist, set this to false
enabled: true
# if you want a custom prefix for the tasklist custom fields, set this to your desired prefix
customFieldsPrefix: "miranum_task_"
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
create table miranum_task_info
(
id_ varchar(36) not null,
description_ varchar(1024),
definitionname_ varchar(255) not null,
assignee_ varchar(255),
instanceid_ varchar(36) not null,
formkey_ varchar(255),
primary key (id_)
id_ VARCHAR(36) NOT NULL,
description_ VARCHAR(1024),
definitionname_ varchar(255) NOT NULL,
assignee_ VARCHAR(255),
instanceid_ VARCHAR(36) NOT NULL,
formkey_ VARCHAR(255),
PRIMARY KEY (id_)
);

CREATE TABLE miranum_task_authorities (
Expand All @@ -17,3 +17,12 @@ CREATE TABLE miranum_task_authorities (
PRIMARY KEY (id_),
FOREIGN KEY (taskinfo_id) REFERENCES MIRANUM_TASK_INFO(id_)
);

CREATE TABLE miranum_task_custom_fields (
id_ VARCHAR(36) NOT NULL,
key_ VARCHAR(255) NOT NULL,
value_ VARCHAR(1024) NOT NULL,
taskinfo_id VARCHAR(36),
PRIMARY KEY (id_),
FOREIGN KEY (taskinfo_id) REFERENCES MIRANUM_TASK_INFO(id_)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1xyw0eh" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.25.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.21.0">
<bpmn:process id="tasklist-example" name="Tasklist Example" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1v8rmgf</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1v8rmgf" sourceRef="StartEvent_1" targetRef="Activity_0iqcr9j" />
<bpmn:endEvent id="Event_1mikqwy">
<bpmn:incoming>Flow_1bsx7k3</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1bsx7k3" sourceRef="Activity_0iqcr9j" targetRef="Event_1mikqwy" />
<bpmn:userTask id="Activity_0iqcr9j" name="Example Usertask" camunda:candidateGroups="group1">
<bpmn:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="miranum_task_form">ExampleForm</camunda:inputParameter>
<camunda:inputParameter name="miranum_task_description">This is a example description</camunda:inputParameter>
<camunda:inputParameter name="miranum_task_type">example</camunda:inputParameter>
<camunda:inputParameter name="miranum_task_foo">bar</camunda:inputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>Flow_1v8rmgf</bpmn:incoming>
<bpmn:outgoing>Flow_1bsx7k3</bpmn:outgoing>
</bpmn:userTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="tasklist-example">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1mikqwy_di" bpmnElement="Event_1mikqwy">
<dc:Bounds x="632" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1guszed_di" bpmnElement="Activity_0iqcr9j">
<dc:Bounds x="370" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1v8rmgf_di" bpmnElement="Flow_1v8rmgf">
<di:waypoint x="215" y="117" />
<di:waypoint x="370" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1bsx7k3_di" bpmnElement="Flow_1bsx7k3">
<di:waypoint x="470" y="117" />
<di:waypoint x="632" y="117" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
### Get Access Token
POST http://keycloak:9090/auth/realms/miranum/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type = password &
client_secret = s3creT &
client_id = miranum &
username = [email protected] &
password = test

> {%
client.global.set("access_token", response.body.access_token);
%}

### Get Group Tasks for group1
GET http://localhost:8083/rest/task/group/group1
Content-Type: application/json
Authorization: Bearer {{ access_token }}

> {%
var firstTaskId = response.body[0].id;
client.global.set("group_task_id", firstTaskId);
%}


### Claim Task for user alex.admin
POST http://localhost:8083/rest/task/{{group_task_id}}/assign
Content-Type: application/json
Authorization: Bearer {{ access_token }}

{
"assignee": "alex.admin"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.miragon.miranum.platform.tasklist;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "miranum.tasklist")
@Getter
@Setter
public class TaskProperties {

private String customFieldsPrefix = "miranum_task_";

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
import org.camunda.bpm.engine.TaskService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@ComponentScan(basePackages = {"io.miragon.miranum.platform.tasklist"})
@EnableConfigurationProperties(TaskProperties.class)
@EnableJpaRepositories(basePackages = {"io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo"})
@EntityScan(basePackages = {"io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo"})
public class TasklistConfiguration {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package io.miragon.miranum.platform.tasklist.adapter.out.task;

import io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo.TaskAuthorityEntity;
import io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo.TaskCustomFieldEntity;
import io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo.TaskInfoEntity;
import io.miragon.miranum.platform.tasklist.domain.Task;
import io.miragon.miranum.platform.tasklist.domain.TaskAuthorities;
import io.miragon.miranum.platform.tasklist.domain.TaskCustomFields;
import io.miragon.miranum.platform.tasklist.domain.TaskInfo;
import org.mapstruct.Mapper;

import java.util.List;
import java.util.stream.Collectors;

@Mapper
public interface TaskMapper {
Expand All @@ -22,6 +26,8 @@ default Task mapToTask(final org.camunda.bpm.engine.task.Task camundaTask, final
.formKey(taskInfo.getFormKey())
.candidateGroups(taskInfo.getCandidateGroups())
.candidateUsers(taskInfo.getCandidateUsers())
.customFields(taskInfo.getCustomFields().stream()
.collect(Collectors.toMap(TaskCustomFields::getKey, TaskCustomFields::getValue)))
.build();
}

Expand All @@ -46,18 +52,42 @@ default TaskInfo mapToTaskInfo(final TaskInfoEntity entity) {
.value(authority.getValue())
.build())
.toList())
.customFields(entity.getCustomFields().stream()
.map(customField -> TaskCustomFields.builder()
.id(customField.getId())
.key(customField.getKey())
.value(customField.getValue())
.build())
.toList())
.build();
}

default TaskInfoEntity mapToTaskInfoEntity(final TaskInfo taskInfo) {
return TaskInfoEntity.builder()
final TaskInfoEntity taskInfoEntity = TaskInfoEntity.builder()
.id(taskInfo.getId())
.description(taskInfo.getDescription())
.definitionName(taskInfo.getDefinitionName())
.instanceId(taskInfo.getInstanceId())
.assignee(taskInfo.getAssignee())
.formKey(taskInfo.getFormKey())
.build();
taskInfoEntity.setAuthorities(taskInfo.getAuthorities().stream()
.map(authority -> TaskAuthorityEntity.builder()
.id(authority.getId())
.type(authority.getType())
.value(authority.getValue())
.taskInfo(taskInfoEntity)
.build())
.toList());
taskInfoEntity.setCustomFields(taskInfo.getCustomFields().stream()
.map(customField -> TaskCustomFieldEntity.builder()
.id(customField.getId())
.key(customField.getKey())
.value(customField.getValue())
.taskInfo(taskInfoEntity)
.build())
.toList());
return taskInfoEntity;
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.miragon.miranum.platform.tasklist.adapter.out.task;

import io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo.TaskAuthorityEntity;
import io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo.TaskInfoEntity;
import io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo.TaskInfoRepository;
import io.miragon.miranum.platform.tasklist.application.port.out.task.TaskOutPort;
Expand Down Expand Up @@ -56,15 +55,6 @@ public Map<String, Object> getTaskData(String user, String taskId) {
@Override
public void createTask(final TaskInfo task) {
final TaskInfoEntity taskInfoEntity = this.taskMapper.mapToTaskInfoEntity(task);
// make sure the TaskAuthorityEntities are persisted too
taskInfoEntity.setAuthorities(task.getAuthorities().stream()
.map(authority -> TaskAuthorityEntity.builder()
.id(authority.getId())
.type(authority.getType())
.value(authority.getValue())
.taskInfo(taskInfoEntity)
.build())
.toList());
this.taskInfoRepository.save(taskInfoEntity);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.miragon.miranum.platform.tasklist.adapter.out.task.taskinfo;

import jakarta.persistence.*;
import lombok.*;

import java.util.UUID;

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "TaskCustomFields")
@Table(name = "MIRANUM_TASK_CUSTOM_FIELDS")
public class TaskCustomFieldEntity {

/**
* The id of the authority
*/
@Id
@Column(name = "id_", unique = true, nullable = false, length = 36)
private String id;

/**
* The name of the custom field
*/
@Column(name = "key_", nullable = false)
private String key;

/**
* The value of the custom field
*/
@Column(name = "value_", nullable = false)
private String value;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "taskinfo_id")
private TaskInfoEntity taskInfo;

@PrePersist
public void generateId() {
if (id == null) {
id = UUID.randomUUID().toString();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ public class TaskInfoEntity {
@Column(name = "formkey_")
private String formKey;

@Builder.Default
@OneToMany(mappedBy = "taskInfo", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<TaskAuthorityEntity> authorities = new ArrayList<>();

@Builder.Default
@OneToMany(mappedBy = "taskInfo", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<TaskCustomFieldEntity> customFields = new ArrayList<>();

}
Loading

0 comments on commit 40bd230

Please sign in to comment.