Skip to content

Commit

Permalink
Merge pull request projectcaluma#144 from sliverc/workitem_with_child…
Browse files Browse the repository at this point in the history
…_case

Add possibility to start sub-workflow on a work item
  • Loading branch information
winged authored Dec 7, 2018
2 parents 40c0ea2 + c9fda45 commit 4c48483
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 12 deletions.
4 changes: 3 additions & 1 deletion caluma/core/mutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ def get_serializer_kwargs(cls, root, info, **input):
instance = cls.get_object(
root,
info,
return_field_type.get_queryset(model_class.objects, info),
return_field_type.get_queryset(
model_class.objects.select_related(), info
),
**input
)
return {
Expand Down
5 changes: 4 additions & 1 deletion caluma/tests/snapshots/snap_test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
meta: JSONString!
document: Document
workItems(before: String, after: String, first: Int, last: Int): WorkItemConnection
parentWorkItem: WorkItem
}
type CaseConnection {
Expand Down Expand Up @@ -763,6 +764,7 @@
input StartCaseInput {
workflow: ID!
meta: JSONString
parentWorkItem: ID
clientMutationId: String
}
Expand Down Expand Up @@ -866,9 +868,10 @@
createdByGroup: String
id: ID!
task: Task!
case: Case!
status: WorkItemStatus!
meta: JSONString!
case: Case!
childCase: Case
}
type WorkItemConnection {
Expand Down
1 change: 1 addition & 0 deletions caluma/workflow/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Meta:

class WorkItemFactory(DjangoModelFactory):
case = SubFactory(CaseFactory)
child_case = SubFactory(CaseFactory)
task = SubFactory(TaskFactory)
status = models.WorkItem.STATUS_READY
meta = {}
Expand Down
25 changes: 25 additions & 0 deletions caluma/workflow/migrations/0005_workitem_child_case.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.17 on 2018-12-07 09:32
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [("workflow", "0004_auto_20181205_1222")]

operations = [
migrations.AddField(
model_name="workitem",
name="child_case",
field=models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="parent_work_item",
to="workflow.Case",
),
)
]
13 changes: 12 additions & 1 deletion caluma/workflow/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ class WorkItem(UUIDModel):
task = models.ForeignKey(
Task, on_delete=models.DO_NOTHING, related_name="work_items"
)
case = models.ForeignKey(Case, related_name="work_items", on_delete=models.CASCADE)
status = models.CharField(choices=STATUS_CHOICE_TUPLE, max_length=50, db_index=True)
meta = JSONField(default={})

case = models.ForeignKey(Case, related_name="work_items", on_delete=models.CASCADE)
child_case = models.OneToOneField(
Case,
related_name="parent_work_item",
on_delete=models.SET_NULL,
null=True,
blank=True,
)
"""
Defines case of a sub-workflow
"""
13 changes: 11 additions & 2 deletions caluma/workflow/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ class StartCaseSerializer(serializers.ModelSerializer):
workflow = serializers.GlobalIDPrimaryKeyRelatedField(
queryset=models.Workflow.objects.select_related("start")
)
parent_work_item = serializers.GlobalIDPrimaryKeyRelatedField(
queryset=models.WorkItem.objects, required=False
)

@transaction.atomic
def create(self, validated_data):
Expand All @@ -140,7 +143,7 @@ def create(self, validated_data):

class Meta:
model = models.Case
fields = ("workflow", "meta")
fields = ("workflow", "meta", "parent_work_item")


class CancelCaseSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -171,7 +174,13 @@ class CompleteWorkItemSerializer(serializers.ModelSerializer):

def validate(self, data):
if self.instance.status != models.WorkItem.STATUS_READY:
raise exceptions.ValidationError("Only ready tasks can be completed.")
raise exceptions.ValidationError("Only ready work items can be completed.")

if self.instance.child_case_id:
if self.instance.child_case.status == models.Case.STATUS_RUNNING:
raise exceptions.ValidationError(
"Work item can only be completed when child case is in a finish state."
)

# TODO: add validation according to task type

Expand Down
1 change: 1 addition & 0 deletions caluma/workflow/tests/snapshots/snap_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"startCase": {
"case": {
"document": {"form": {"slug": "sound-air-mission"}},
"parentWorkItem": {"status": "READY"},
"status": "RUNNING",
"workItems": {"edges": [{"node": {"status": "READY"}}]},
},
Expand Down
4 changes: 2 additions & 2 deletions caluma/workflow/tests/snapshots/snap_test_work_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
"allWorkItems": {"edges": [{"node": {"status": "READY"}}]}
}

snapshots["test_complete_work_item_last[ready-True] 1"] = {
snapshots["test_complete_work_item_last[ready-completed-True] 1"] = {
"completeWorkItem": {
"clientMutationId": None,
"workItem": {"case": {"status": "COMPLETED"}, "status": "COMPLETED"},
}
}

snapshots["test_complete_work_item_with_next[ready] 1"] = {
snapshots["test_complete_work_item_with_next[ready-None] 1"] = {
"completeWorkItem": {
"clientMutationId": None,
"workItem": {
Expand Down
7 changes: 5 additions & 2 deletions caluma/workflow/tests/test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def test_query_all_cases(db, snapshot, case, flow, schema_executor):
snapshot.assert_match(result.data)


def test_start_case(db, snapshot, workflow, schema_executor):
def test_start_case(db, snapshot, workflow, work_item, schema_executor):
query = """
mutation StartCase($input: StartCaseInput!) {
startCase(input: $input) {
Expand All @@ -33,6 +33,9 @@ def test_start_case(db, snapshot, workflow, schema_executor):
}
}
status
parentWorkItem {
status
}
workItems {
edges {
node {
Expand All @@ -46,7 +49,7 @@ def test_start_case(db, snapshot, workflow, schema_executor):
}
"""

inp = {"input": {"workflow": workflow.slug}}
inp = {"input": {"workflow": workflow.slug, "parentWorkItem": str(work_item.pk)}}
result = schema_executor(query, variables=inp)

assert not result.errors
Expand Down
12 changes: 9 additions & 3 deletions caluma/workflow/tests/test_work_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ def test_query_all_work_items(db, snapshot, work_item, schema_executor):


@pytest.mark.parametrize(
"work_item__status,success",
[(models.WorkItem.STATUS_READY, True), (models.WorkItem.STATUS_COMPLETED, False)],
"work_item__status,case__status,success",
[
(models.WorkItem.STATUS_READY, models.Case.STATUS_COMPLETED, True),
(models.WorkItem.STATUS_COMPLETED, models.Case.STATUS_COMPLETED, False),
(models.WorkItem.STATUS_READY, models.Case.STATUS_RUNNING, False),
],
)
def test_complete_work_item_last(db, snapshot, work_item, success, schema_executor):
query = """
Expand All @@ -49,7 +53,9 @@ def test_complete_work_item_last(db, snapshot, work_item, success, schema_execut
snapshot.assert_match(result.data)


@pytest.mark.parametrize("work_item__status", [models.WorkItem.STATUS_READY])
@pytest.mark.parametrize(
"work_item__status,work_item__child_case", [(models.WorkItem.STATUS_READY, None)]
)
def test_complete_work_item_with_next(
db, snapshot, work_item, flow, task_factory, schema_executor
):
Expand Down

0 comments on commit 4c48483

Please sign in to comment.