Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Won 20 zwd file upload functionaliteit in task bpmn #36

Merged
merged 5 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions app/apps/cases/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ def validate_document(self, value):
return value


class CaseDocumentWithTaskSerializer(CaseDocumentSerializer):
author = serializers.HiddenField(default=serializers.CurrentUserDefault())
case_user_task_id = serializers.CharField(
required=False, allow_null=True, write_only=True
)

class Meta(CaseDocumentSerializer.Meta):
fields = CaseDocumentSerializer.Meta.fields + (
"case_user_task_id",
"author",
)


class StartWorkflowSerializer(serializers.Serializer):
workflow_option_id = serializers.PrimaryKeyRelatedField(
queryset=WorkflowOption.objects.all()
Expand Down
3 changes: 1 addition & 2 deletions app/apps/cases/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ def create_document(self, request):
@action(detail=True, methods=["get"], url_path="documents")
def get_documents(self, request, pk=None):
case = self.get_object()
documents = CaseDocument.objects.filter(case=case)
serializer = CaseDocumentSerializer(documents, many=True)
serializer = CaseDocumentSerializer(case.documents, many=True)
return Response(serializer.data)

@action(
Expand Down

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/apps/workflow/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ def _parse_task_spec_form(self, form):
"string": "text",
"long": "number",
"expression": "expression",
"file": "file",
}
fields = [
{
Expand Down
120 changes: 120 additions & 0 deletions app/apps/workflow/tests/tests_api.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from unittest.mock import patch
from django.core import management
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from apps.homeownerassociation.models import HomeownerAssociation
from apps.cases.models import Case, CaseDocument
from apps.workflow.models import CaseUserTask, CaseWorkflow, GenericCompletedTask
from utils.test_utils import get_authenticated_client, get_unauthenticated_client
import uuid
from django.core.files.uploadedfile import SimpleUploadedFile


class CaseUserTaskApiTests(APITestCase):
Expand All @@ -27,3 +33,117 @@ def test_authenticated_get_empty(self):
response = self.client.get(url)
data = response.json()
self.assertEqual(data, [])

@patch("apps.workflow.views.complete_generic_user_task_and_create_new_user_tasks")
def test_complete_file_task(
self, complete_generic_user_task_and_create_new_user_tasks
):
complete_generic_user_task_and_create_new_user_tasks.return_value = (
"task completed"
)
case, case_user_task = self._create_case_and_task()

url = reverse("generictasks-complete-file-task")
data = {
"case_user_task_id": case_user_task.id,
"case": case.id,
"name": "test_document",
"document": SimpleUploadedFile(
"test_document.pdf", b"file_content", content_type="application/pdf"
),
}
response = self.client.post(url, data=data, format="multipart")

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(
GenericCompletedTask.objects.filter(
case_user_task_id=case_user_task.id
).exists()
)
self.assertTrue(CaseDocument.objects.filter(name="test_document").exists())

@patch("apps.workflow.views.complete_generic_user_task_and_create_new_user_tasks")
def test_complete_task(self, complete_generic_user_task_and_create_new_user_tasks):
complete_generic_user_task_and_create_new_user_tasks.return_value = (
"task completed"
)
case, case_user_task = self._create_case_and_task()

url = reverse("generictasks-complete-task")
data = {
"case_user_task_id": case_user_task.id,
"case": case.id,
"variables": {"test": "test"},
}
response = self.client.post(url, data, format="json")

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(
GenericCompletedTask.objects.filter(
case_user_task_id=case_user_task.id
).exists()
)

def test_get_case_user_tasks(self):
case, case_user_task = self._create_case_and_task()
url = reverse("tasks-list")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertGreaterEqual(len(response.json()), 1)

def test_get_case_user_task_detail(self):
_, case_user_task = self._create_case_and_task()
url = reverse("tasks-detail", kwargs={"pk": case_user_task.id})
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json()["id"], case_user_task.id)

def test_complete_task_invalid_id(self):
url = reverse("generictasks-complete-task")
data = {
"case_user_task_id": uuid.uuid4(),
"case": uuid.uuid4(),
"variables": {"test": "test"},
}
response = self.client.post(url, data, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_complete_file_task_missing_file(self):
case, case_user_task = self._create_case_and_task()
url = reverse("generictasks-complete-file-task")
data = {
"case_user_task_id": case_user_task.id,
"case": case.id,
"name": "test_document",
}
response = self.client.post(url, data, format="multipart")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def _create_case_and_task(self):
case_id = self._create_case()
case = Case.objects.get(id=case_id)
case_wf = CaseWorkflow.objects.create(
case=case, completed=False, workflow_type="process_vve_ok"
)
case_user_task = CaseUserTask.objects.create(
task_name="task1",
completed=False,
case=case,
task_id=uuid.uuid4(),
due_date="2021-01-01",
workflow_id=case_wf.id,
)
return case, case_user_task

@patch("apps.cases.views.CaseViewSet.start_workflow")
def _create_case(self, mock_start_workflow):
hoa = HomeownerAssociation.objects.create(
name="HOA", number_of_appartments=12, build_year=2010
)
mock_start_workflow.return_value = "task_start_worflow: completed"
url = reverse("cases-list")
data = {"description": "Test case description", "homeowner_association": hoa.id}

response = self.client.post(url, data, format="json")
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
return response.data["id"]
106 changes: 65 additions & 41 deletions app/apps/workflow/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging

from rest_framework import status
from apps.cases.serializers import CaseDocumentWithTaskSerializer
from apps.workflow.task_completion import (
complete_generic_user_task_and_create_new_user_tasks,
)
Expand All @@ -9,12 +10,12 @@
get_bpmn_model_versions_and_files,
map_variables_on_task_spec_form,
)
from django.http import HttpResponse, HttpResponseBadRequest
from django.http import HttpResponse
from drf_spectacular.utils import extend_schema
from rest_framework import mixins, viewsets
from rest_framework.response import Response
from rest_framework.decorators import action

from django.db import transaction
from .models import CaseUserTask, GenericCompletedTask
from .serializers import (
BpmnModelListSerializer,
Expand All @@ -40,56 +41,80 @@ class GenericCompletedTaskViewSet(viewsets.GenericViewSet):
serializer_class = GenericCompletedTaskSerializer
queryset = GenericCompletedTask.objects.all()

@extend_schema(
description="Complete GenericCompletedTask",
responses={200: None},
)
@extend_schema(description="Complete GenericCompletedTask", responses={200: None})
@action(
detail=False,
url_path="complete",
methods=["post"],
serializer_class=GenericCompletedTaskCreateSerializer,
)
def complete_task(self, request):
context = {"request": self.request}

serializer = GenericCompletedTaskCreateSerializer(
data=request.data, context=context
data=request.data, context={"request": request}
)
if serializer.is_valid():
data = serializer.validated_data
return self._complete_task_common(serializer)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

variables = data.get("variables", {})
task = CaseUserTask.objects.get(
id=data["case_user_task_id"], completed=False
)
from .user_tasks import get_task_by_name

user_task_type = get_task_by_name(task.task_name)
user_task = user_task_type(task)
if user_task and user_task.mapped_form_data(variables):
variables["mapped_form_data"] = user_task.mapped_form_data(variables)
else:
variables["mapped_form_data"] = map_variables_on_task_spec_form(
variables, task.form
)
data.update(
{
"description": task.name,
"task_name": task.task_name,
"variables": variables,
}
@action(
detail=False,
url_path="complete-file-task",
methods=["post"],
serializer_class=CaseDocumentWithTaskSerializer,
)
def complete_file_task(self, request):
serializer = CaseDocumentWithTaskSerializer(
data=request.data, context={"request": request}
)
if serializer.is_valid():
return self._complete_task_common(serializer, save_document=True)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@transaction.atomic
def _complete_task_common(self, serializer, save_document=False):

data = serializer.validated_data

case_user_task_id = data.pop("case_user_task_id")
author = data.pop("author")
variables = data.get("variables", {})
task = CaseUserTask.objects.get(id=case_user_task_id, completed=False)
from apps.workflow.user_tasks import get_task_by_name

user_task_type = get_task_by_name(task.task_name)
user_task = user_task_type(task)

if user_task and user_task.mapped_form_data(variables):
variables["mapped_form_data"] = user_task.mapped_form_data(variables)
else:
variables["mapped_form_data"] = map_variables_on_task_spec_form(
variables, task.form
)

try:
case_user_task = GenericCompletedTask.objects.create(**data)
complete_generic_user_task_and_create_new_user_tasks(case_user_task)
return HttpResponse(
f"CaseUserTask {data['case_user_task_id']} has been completed"
)
except Exception as e:
raise e
return HttpResponseBadRequest("Invalid request")
# Only save the document if it is a file task so the file gets uploaded
if save_document:
variables["mapped_form_data"]["document_name"] = {
"label": "Document",
"value": serializer.validated_data.get("name"),
}
serializer.save()

task_data = {
"case_user_task_id": case_user_task_id,
"description": task.name,
"task_name": task.task_name,
"variables": variables,
"case": task.case,
"author": author,
}

case_user_task = GenericCompletedTask.objects.create(**task_data)
complete_generic_user_task_and_create_new_user_tasks(case_user_task)

return Response(
{"message": f"CaseUserTask {case_user_task_id} has been completed"},
status=status.HTTP_200_OK,
)


class BpmnViewSet(viewsets.GenericViewSet):
Expand Down Expand Up @@ -136,5 +161,4 @@ def get_model_versions(self, request, model_name):
)
def get_bpmn_file(self, request, model_name, version):
content = get_bpmn_file(model_name, version)
# Return the file content as an XML response
return HttpResponse(content, content_type="application/xml")
1 change: 1 addition & 0 deletions app/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ def get_redis_url():
"1.3.0": {},
"1.4.0": {},
"1.5.0": {},
"1.6.0": {},
},
},
"sub_workflow": {
Expand Down
Loading