ManyToMany fields dont support e.g. on_delete so we need to discard unattached
triggers and actions manually
"""
- for trigger in WorkflowTrigger.objects.all():
- if trigger.workflows.all().count() == 0:
- trigger.delete()
+ WorkflowTrigger.objects.annotate(
+ workflow_count=Count("workflows"),
+ ).filter(workflow_count=0).delete()
- for action in WorkflowAction.objects.all():
- if action.workflows.all().count() == 0:
- action.delete()
+ WorkflowAction.objects.annotate(
+ workflow_count=Count("workflows"),
+ ).filter(workflow_count=0).delete()
WorkflowActionEmail.objects.filter(action=None).delete()
WorkflowActionWebhook.objects.filter(action=None).delete()
return instance
- def to_representation(self, instance: Workflow) -> dict[str, Any]:
- data = super().to_representation(instance)
- actions = instance.actions.order_by("order", "pk")
- data["actions"] = WorkflowActionSerializer(
- actions,
- many=True,
- context=self.context,
- ).data
- return data
-
class TrashSerializer(SerializerWithPerms):
documents = serializers.ListField(
self.action.assign_correspondent.pk,
)
+ def test_api_get_workflow_actions_ordered(self) -> None:
+ """
+ GIVEN:
+ - A workflow with two actions added in reverse order (order=1 before order=0)
+ WHEN:
+ - API is called to get workflows
+ THEN:
+ - Actions are returned sorted by order ascending
+ """
+ # Created before action_first so its pk is lower — ensures pk order
+ # disagrees with the order field, catching regressions if order_by is removed.
+ action_second = WorkflowAction.objects.create(
+ assign_title="Second action",
+ order=1,
+ )
+ action_first = WorkflowAction.objects.create(
+ assign_title="First action",
+ order=0,
+ )
+ self.workflow.actions.add(action_second)
+ self.workflow.actions.add(action_first)
+
+ response = self.client.get(self.ENDPOINT, format="json")
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ resp_actions = response.data["results"][0]["actions"]
+ action_ids = [a["id"] for a in resp_actions]
+ self.assertIn(action_first.id, action_ids)
+ self.assertIn(action_second.id, action_ids)
+ self.assertLess(
+ action_ids.index(action_first.id),
+ action_ids.index(action_second.id),
+ )
+
def test_api_create_workflow(self) -> None:
"""
GIVEN:
Workflow.objects.all()
.order_by("order")
.prefetch_related(
- "triggers",
- "actions",
+ Prefetch(
+ "triggers",
+ queryset=WorkflowTrigger.objects.prefetch_related(
+ "filter_has_tags",
+ "filter_has_all_tags",
+ "filter_has_not_tags",
+ "filter_has_any_correspondents",
+ "filter_has_not_correspondents",
+ "filter_has_any_document_types",
+ "filter_has_not_document_types",
+ "filter_has_any_storage_paths",
+ "filter_has_not_storage_paths",
+ ),
+ ),
+ Prefetch(
+ "actions",
+ queryset=WorkflowAction.objects.order_by(
+ "order",
+ "pk",
+ ).prefetch_related(
+ "assign_tags",
+ "assign_view_users",
+ "assign_view_groups",
+ "assign_change_users",
+ "assign_change_groups",
+ "assign_custom_fields",
+ "remove_tags",
+ "remove_correspondents",
+ "remove_document_types",
+ "remove_storage_paths",
+ "remove_custom_fields",
+ "remove_owners",
+ "remove_view_users",
+ "remove_view_groups",
+ "remove_change_users",
+ "remove_change_groups",
+ ),
+ ),
)
)