Skip to content

Commit

Permalink
Merge pull request #24 from Amsterdam/feature/130547-add-subtasks
Browse files Browse the repository at this point in the history
Add the possibility to create subtasks
  • Loading branch information
NvdLaan authored Nov 25, 2024
2 parents 7656afe + edaa1ba commit 0abc5b7
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 32 deletions.
7 changes: 7 additions & 0 deletions app/apps/cases/serializers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from apps.workflow.models import WorkflowOption
from apps.homeownerassociation.serializers import (
ContactSerializer,
CaseHomeownerAssociationSerializer,
Expand Down Expand Up @@ -70,3 +71,9 @@ def validate_document(self, value):
raise serializers.ValidationError("File type not allowed")

return value


class StartWorkflowSerializer(serializers.Serializer):
workflow_option_id = serializers.PrimaryKeyRelatedField(
queryset=WorkflowOption.objects.all()
)
53 changes: 49 additions & 4 deletions app/apps/cases/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from apps.homeownerassociation.models import Contact
from apps.events.serializers import CaseEventSerializer
from apps.events.mixins import CaseEventsMixin
from apps.workflow.models import CaseWorkflow
from apps.workflow.serializers import CaseWorkflowSerializer
from apps.workflow.models import CaseWorkflow, WorkflowOption
from apps.workflow.serializers import CaseWorkflowSerializer, WorkflowOptionSerializer
from rest_framework import mixins, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
Expand All @@ -14,6 +14,7 @@
CaseDocumentSerializer,
CaseSerializer,
CaseListSerializer,
StartWorkflowSerializer,
)
from django.shortcuts import get_object_or_404
from django.core.files.storage import default_storage
Expand All @@ -27,7 +28,7 @@ class CaseViewSet(
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
):
queryset = Case.objects.all()
queryset = Case.objects.all().prefetch_related("homeowner_association")
serializer_class = CaseSerializer

def get_serializer_class(self):
Expand All @@ -45,7 +46,7 @@ def get_serializer_class(self):
@action(detail=True, methods=["get"], url_path="workflows")
def get_workflows(self, request, pk=None):
case = self.get_object()
workflows = CaseWorkflow.objects.filter(case=case)
workflows = CaseWorkflow.objects.filter(case=case, completed=False)
serializer = CaseWorkflowSerializer(workflows, many=True)
return Response(serializer.data)

Expand Down Expand Up @@ -99,3 +100,47 @@ def delete_document(self, request, pk=None, doc_id=None):
case_document = get_object_or_404(CaseDocument, case=case, id=doc_id)
case_document.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

@action(
detail=True,
url_path="processes/start",
methods=["post"],
serializer_class=StartWorkflowSerializer,
)
def start_process(self, request, pk):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
data = serializer.validated_data
case = self.get_object()
instance = data["workflow_option_id"]

workflow_type = "sub_workflow"
CaseWorkflow.objects.create(
case=case,
workflow_type=workflow_type,
workflow_message_name=instance.message_name,
)

return Response(
data=f"Workflow has started {str(instance)}",
status=status.HTTP_200_OK,
)

return Response(
data="Workflow has not started. serializer not valid",
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)

@action(
detail=False,
url_path="processes",
url_name="processes",
methods=["get"],
serializer_class=WorkflowOptionSerializer,
)
def get_workflow_options(self, request):
serializer = WorkflowOptionSerializer(
WorkflowOption.objects.all(),
many=True,
)
return Response(serializer.data)
11 changes: 10 additions & 1 deletion app/apps/workflow/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.contrib import admin

from .models import CaseUserTask, CaseWorkflow, GenericCompletedTask
from .models import CaseUserTask, CaseWorkflow, GenericCompletedTask, WorkflowOption


@admin.register(CaseWorkflow)
Expand Down Expand Up @@ -58,3 +58,12 @@ class GenericCompletedTaskAdmin(admin.ModelAdmin):
"description",
"task_name",
)


@admin.register(WorkflowOption)
class WorkflowOptionAdmin(admin.ModelAdmin):
list_display = (
"id",
"name",
"message_name",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0q4k183" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.25.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.15.0">
<bpmn:message id="Message_1honxk2" name="event_start_extra_information_process" />
<bpmn:message id="Message_1vtwc8d" name="event_start_extra_information_process-2" />
<bpmn:collaboration id="Collaboration_1mi3u0g">
<bpmn:participant id="Participant_1o1s41c" name="ZWD Sub taken" processRef="sub_workflow" />
</bpmn:collaboration>
<bpmn:process id="sub_workflow" name="ZWD Sub taken" isExecutable="true">
<bpmn:laneSet id="LaneSet_1rr713p">
<bpmn:lane id="Lane_Projectmedewerker" name="Projectmedewerker">
<bpmn:flowNodeRef>Event_1kljwfy</bpmn:flowNodeRef>
<bpmn:flowNodeRef>start_1</bpmn:flowNodeRef>
<bpmn:flowNodeRef>task_verwerken_extra_informatie</bpmn:flowNodeRef>
</bpmn:lane>
</bpmn:laneSet>
<bpmn:endEvent id="Event_1kljwfy">
<bpmn:incoming>Flow_1diaqio</bpmn:incoming>
</bpmn:endEvent>
<bpmn:startEvent id="start_1">
<bpmn:outgoing>Flow_1rb6647</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_10bhnu0" messageRef="Message_1honxk2" />
</bpmn:startEvent>
<bpmn:userTask id="task_verwerken_extra_informatie" name="Verwerken extra informatie">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="extra_informatie" label="Toelichting" type="string" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>Flow_1rb6647</bpmn:incoming>
<bpmn:outgoing>Flow_1diaqio</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1diaqio" sourceRef="task_verwerken_extra_informatie" targetRef="Event_1kljwfy" />
<bpmn:sequenceFlow id="Flow_1rb6647" sourceRef="start_1" targetRef="task_verwerken_extra_informatie" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1mi3u0g">
<bpmndi:BPMNShape id="Participant_1o1s41c_di" bpmnElement="Participant_1o1s41c" isHorizontal="true" isExpanded="true">
<dc:Bounds x="160" y="85" width="600" height="370" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Lane_1fvwbij_di" bpmnElement="Lane_Projectmedewerker" isHorizontal="true">
<dc:Bounds x="190" y="85" width="570" height="370" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1kljwfy_di" bpmnElement="Event_1kljwfy">
<dc:Bounds x="552" y="242" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1bzgjxg_di" bpmnElement="start_1">
<dc:Bounds x="319" y="242" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="171" y="175" width="78" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1k4bt0u_di" bpmnElement="task_verwerken_extra_informatie">
<dc:Bounds x="410" y="220" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1diaqio_di" bpmnElement="Flow_1diaqio">
<di:waypoint x="510" y="260" />
<di:waypoint x="552" y="260" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1rb6647_di" bpmnElement="Flow_1rb6647">
<di:waypoint x="355" y="260" />
<di:waypoint x="410" y="260" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
9 changes: 9 additions & 0 deletions app/apps/workflow/fixtures/fixture.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[{
"model": "workflow.workflowoption",
"pk": 1,
"fields": {
"name": "Extra informatie",
"message_name": "event_start_extra_information_process"
}
}
]
32 changes: 32 additions & 0 deletions app/apps/workflow/migrations/0007_workflowoption.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 5.0.8 on 2024-11-20 09:32

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("workflow", "0006_caseworkflow_completed"),
]

operations = [
migrations.CreateModel(
name="WorkflowOption",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255)),
("message_name", models.CharField(max_length=255)),
],
options={
"ordering": ["name"],
},
),
]
27 changes: 25 additions & 2 deletions app/apps/workflow/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from SpiffWorkflow.camunda.parser.CamundaParser import CamundaParser
from SpiffWorkflow.camunda.serializer.config import CAMUNDA_CONFIG
from SpiffWorkflow.camunda.specs.user_task import UserTask
from SpiffWorkflow.camunda.specs.event_definitions import MessageEventDefinition
from SpiffWorkflow.bpmn import BpmnEvent

from .managers import BulkCreateSignalsManager
from .tasks import (
Expand Down Expand Up @@ -86,6 +88,17 @@ def start(self):
)
initial_data.update(self.data)
workflow = self._initial_data(workflow, initial_data)
if self.workflow_message_name:
workflow.refresh_waiting_tasks()
workflow.do_engine_steps()
# Only the message name is relevant here, the other parameters are not used but the docs don't really specify what they are used for.
workflow.catch(
BpmnEvent(
MessageEventDefinition(self.workflow_message_name),
{"result_var": "result_var", "payload": "payload"},
)
)

workflow = self._update_workflow(workflow)
self._update_db(workflow)
return
Expand All @@ -108,14 +121,13 @@ def _get_workflow_path(
self,
workflow_type,
theme_name="default",
workflow_version="1.3.0",
):
path = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"bpmn_files",
theme_name.lower(),
workflow_type.lower(),
workflow_version.lower(),
self.workflow_version.lower(),
)
return path

Expand Down Expand Up @@ -343,3 +355,14 @@ def __get_event_values__(self):
"description": self.description,
"variables": variables,
}


class WorkflowOption(models.Model):
name = models.CharField(max_length=255)
message_name = models.CharField(max_length=255)

def __str__(self):
return f"{self.name} - {self.message_name}"

class Meta:
ordering = ["name"]
31 changes: 30 additions & 1 deletion app/apps/workflow/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from rest_framework import serializers
from rest_framework.fields import empty

from .models import CaseUserTask, CaseWorkflow, GenericCompletedTask
from .models import CaseUserTask, CaseWorkflow, GenericCompletedTask, WorkflowOption


class CaseUserTaskSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -38,6 +38,27 @@ class Meta:
)


class CaseUserTaskListSerializer(serializers.ModelSerializer):
case = serializers.PrimaryKeyRelatedField(queryset=Case.objects.all())
homeowner_association = serializers.SerializerMethodField()

def get_homeowner_association(self, obj):
return (
obj.case.homeowner_association.name
if obj.case.homeowner_association
else None
)

class Meta:
model = CaseUserTask
fields = (
"id",
"name",
"case",
"homeowner_association",
)


class CaseWorkflowSerializer(serializers.ModelSerializer):
tasks = serializers.SerializerMethodField()

Expand All @@ -52,6 +73,7 @@ class Meta:
"workflow_message_name",
"data",
"tasks",
"completed",
)

@extend_schema_field(CaseUserTaskSerializer(many=True))
Expand Down Expand Up @@ -127,6 +149,7 @@ def run_validation(self, data=empty):

class WorkflowSpecConfigThemeTypeSerializer(serializers.Serializer):
process_vve_ok = WorkflowSpecConfigThemeSerializer(required=False)
sub_workflow = WorkflowSpecConfigThemeSerializer(required=False)

def run_validation(self, data=empty):
if data is not empty:
Expand Down Expand Up @@ -163,3 +186,9 @@ class BpmnModelSerializer(serializers.Serializer):
version = serializers.CharField(max_length=100)
file_name = serializers.CharField(max_length=100)
model = serializers.CharField(max_length=100)


class WorkflowOptionSerializer(serializers.ModelSerializer):
class Meta:
model = WorkflowOption
fields = "id", "name", "message_name"
Loading

0 comments on commit 0abc5b7

Please sign in to comment.