Skip to content

Commit

Permalink
feat(workflow): add mutation and api function for canceling work items
Browse files Browse the repository at this point in the history
  • Loading branch information
anehx committed Jul 31, 2020
1 parent 9b2e56a commit 0b04def
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 1 deletion.
21 changes: 21 additions & 0 deletions caluma/caluma_workflow/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,24 @@ def cancel_case(case: models.Case, user: BaseUser) -> models.Case:
domain_logic.CancelCaseLogic.post_cancel(case, user)

return case


def cancel_work_item(work_item: models.WorkItem, user: BaseUser) -> models.WorkItem:
"""
Cancel a work item (just like `CancelWorkItem`).
>>> cancel_work_item(
... work_item=models.WorkItem.first(),
... user=AnonymousUser()
... )
<WorkItem: WorkItem object (some-uuid)>
"""
domain_logic.CancelWorkItemLogic.validate_for_cancel(work_item)

validated_data = domain_logic.CancelWorkItemLogic.pre_cancel({}, user)

update_model(models.WorkItem.objects.get(pk=work_item.pk), validated_data)

domain_logic.CancelWorkItemLogic.post_cancel(work_item, user)

return work_item
27 changes: 27 additions & 0 deletions caluma/caluma_workflow/domain_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,30 @@ def post_cancel(case, user):
)

return case


class CancelWorkItemLogic:
@staticmethod
def validate_for_cancel(work_item):
if work_item.status != models.WorkItem.STATUS_READY:
raise ValidationError("Only READY work items can be cancelled")

@staticmethod
def pre_cancel(validated_data, user):
validated_data["status"] = models.WorkItem.STATUS_CANCELED
validated_data["closed_at"] = timezone.now()
validated_data["closed_by_user"] = user.username
validated_data["closed_by_group"] = user.group

return validated_data

@staticmethod
def post_cancel(work_item, user):
send_event(
events.cancelled_work_item,
sender="post_cancel_work_item",
work_item=work_item,
user=user,
)

return work_item
7 changes: 7 additions & 0 deletions caluma/caluma_workflow/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ class Meta:
model_operations = ["update"]


class CancelWorkItem(Mutation):
class Meta:
serializer_class = serializers.CancelWorkItemSerializer
model_operations = ["update"]


class SaveWorkItem(Mutation):
class Meta:
serializer_class = serializers.SaveWorkItemSerializer
Expand Down Expand Up @@ -310,6 +316,7 @@ class Mutation(object):
cancel_case = CancelCase().Field()
complete_work_item = CompleteWorkItem().Field()
skip_work_item = SkipWorkItem().Field()
cancel_work_item = CancelWorkItem().Field()
save_work_item = SaveWorkItem().Field()
create_work_item = CreateWorkItem().Field()

Expand Down
28 changes: 28 additions & 0 deletions caluma/caluma_workflow/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,34 @@ class Meta:
fields = ("id",)


class CancelWorkItemSerializer(serializers.ModelSerializer):
id = serializers.GlobalIDField()

def validate(self, data):
try:
domain_logic.CancelWorkItemLogic.validate_for_cancel(self.instance)
except ValidationError as e:
raise exceptions.ValidationError(str(e))

return data

def update(self, work_item, validated_data):
user = self.context["request"].user

validated_data = domain_logic.CancelWorkItemLogic.pre_cancel(
validated_data, user
)

work_item = super().update(work_item, validated_data)
work_item = domain_logic.CancelWorkItemLogic.post_cancel(work_item, user)

return work_item

class Meta:
model = models.WorkItem
fields = ("id",)


class SaveWorkItemSerializer(SendEventSerializerMixin, serializers.ModelSerializer):
work_item = serializers.GlobalIDField(source="id")
name = CharField(
Expand Down
49 changes: 49 additions & 0 deletions caluma/caluma_workflow/tests/test_work_item.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json

import pytest
from django.core.exceptions import ValidationError
from graphene.utils.str_converters import to_const

from ...caluma_core.relay import extract_global_id
Expand Down Expand Up @@ -1108,3 +1109,51 @@ def test_complete_work_item_same_task_multiple_workflows(

assert case_1.status == models.Case.STATUS_RUNNING
assert case_2.status == models.Case.STATUS_COMPLETED


@pytest.mark.parametrize("use_graphql_api", [True, False])
@pytest.mark.parametrize(
"work_item__status,success,expected_status",
[
(models.WorkItem.STATUS_READY, True, models.WorkItem.STATUS_CANCELED),
(models.WorkItem.STATUS_SKIPPED, False, models.WorkItem.STATUS_SKIPPED),
],
)
def test_cancel_work_item(
db,
work_item,
schema_executor,
admin_user,
use_graphql_api,
success,
expected_status,
):
error_msg = "Only READY work items can be cancelled"

if use_graphql_api:
query = """
mutation CancelWorkItem($input: CancelWorkItemInput!) {
cancelWorkItem(input: $input) {
clientMutationId
}
}
"""

result = schema_executor(query, variable_values={"input": {"id": work_item.pk}})

if success:
assert not bool(result.errors)
else:
assert error_msg in str(result.errors[0])
else:
if success:
api.cancel_work_item(work_item, admin_user)
else:
with pytest.raises(ValidationError) as error:
api.cancel_work_item(work_item, admin_user)

assert error_msg in str(error.value)

work_item.refresh_from_db()

assert work_item.status == expected_status
11 changes: 11 additions & 0 deletions caluma/tests/__snapshots__/test_schema.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@
clientMutationId: String
}

input CancelWorkItemInput {
id: ID!
clientMutationId: String
}

type CancelWorkItemPayload {
workItem: WorkItem
clientMutationId: String
}

type Case implements Node {
createdAt: DateTime!
modifiedAt: DateTime!
Expand Down Expand Up @@ -1050,6 +1060,7 @@
cancelCase(input: CancelCaseInput!): CancelCasePayload
completeWorkItem(input: CompleteWorkItemInput!): CompleteWorkItemPayload
skipWorkItem(input: SkipWorkItemInput!): SkipWorkItemPayload
cancelWorkItem(input: CancelWorkItemInput!): CancelWorkItemPayload
saveWorkItem(input: SaveWorkItemInput!): SaveWorkItemPayload
createWorkItem(input: CreateWorkItemInput!): CreateWorkItemPayload
saveForm(input: SaveFormInput!): SaveFormPayload
Expand Down
2 changes: 1 addition & 1 deletion docs/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ in case the event sends additional arguments in the future.
| --------------------- | ----------------------------------------------------------------- | ------------------- |
| `created_work_item` | `CreateWorkItem`, `SaveWorkItem`, `StartCase`, `CompleteWorkItem` | `work_item`, `user` |
| `completed_work_item` | `CompleteWorkItem` | `work_item`, `user` |
| `cancelled_work_item` | `CancelCase` | `work_item`, `user` |
| `cancelled_work_item` | `CancelCase`, `CancelWorkItem` | `work_item`, `user` |
| `skipped_work_item` | `SkipWorkItem` | `work_item`, `user` |
| `created_case` | `SaveCase`, `StartCase` | `case`, `user` |
| `completed_case` | `CompleteWorkItem` | `case`, `user` |
Expand Down

0 comments on commit 0b04def

Please sign in to comment.