From 96ac7b23364afbbdec3ba4ec7c1c620848aaac01 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 2 Mar 2026 08:21:14 -0800 Subject: [PATCH] Tweak: Ignore version docs for workflows (#12217) --- src/documents/consumer.py | 7 ++ src/documents/signals/handlers.py | 8 +++ src/documents/tasks.py | 20 ++++-- src/documents/tests/test_workflows.py | 96 +++++++++++++++++++++++++++ src/documents/views.py | 10 +++ 5 files changed, 137 insertions(+), 4 deletions(-) diff --git a/src/documents/consumer.py b/src/documents/consumer.py index d8682a6d7..023ff1f55 100644 --- a/src/documents/consumer.py +++ b/src/documents/consumer.py @@ -43,6 +43,7 @@ from documents.plugins.helpers import ProgressManager from documents.plugins.helpers import ProgressStatusOptions from documents.signals import document_consumption_finished from documents.signals import document_consumption_started +from documents.signals import document_updated from documents.signals.handlers import run_workflows from documents.templating.workflows import parse_w_workflow_placeholders from documents.utils import copy_basic_file_stats @@ -646,6 +647,12 @@ class ConsumerPlugin( # This triggers things like file renaming document.save() + if document.root_document_id: + document_updated.send( + sender=self.__class__, + document=document.root_document, + ) + # Delete the file only if it was successfully consumed self.log.debug(f"Deleting original file {self.input_doc.original_file}") self.input_doc.original_file.unlink() diff --git a/src/documents/signals/handlers.py b/src/documents/signals/handlers.py index 204d7aea4..5fb7ef8c5 100644 --- a/src/documents/signals/handlers.py +++ b/src/documents/signals/handlers.py @@ -782,6 +782,14 @@ def run_workflows( """ use_overrides = overrides is not None + + if isinstance(document, Document) and document.root_document_id is not None: + logger.debug( + "Skipping workflow execution for version document %s", + document.pk, + ) + return None + if original_file is None: original_file = ( document.source_path if not use_overrides else document.original_file diff --git a/src/documents/tasks.py b/src/documents/tasks.py index cee038072..c6a158334 100644 --- a/src/documents/tasks.py +++ b/src/documents/tasks.py @@ -452,13 +452,22 @@ def check_scheduled_workflows() -> None: match trigger.schedule_date_field: case WorkflowTrigger.ScheduleDateField.ADDED: - documents = Document.objects.filter(added__lte=threshold) + documents = Document.objects.filter( + root_document__isnull=True, + added__lte=threshold, + ) case WorkflowTrigger.ScheduleDateField.CREATED: - documents = Document.objects.filter(created__lte=threshold) + documents = Document.objects.filter( + root_document__isnull=True, + created__lte=threshold, + ) case WorkflowTrigger.ScheduleDateField.MODIFIED: - documents = Document.objects.filter(modified__lte=threshold) + documents = Document.objects.filter( + root_document__isnull=True, + modified__lte=threshold, + ) case WorkflowTrigger.ScheduleDateField.CUSTOM_FIELD: # cap earliest date to avoid massive scans @@ -496,7 +505,10 @@ def check_scheduled_workflows() -> None: ) ] - documents = Document.objects.filter(id__in=matched_ids) + documents = Document.objects.filter( + root_document__isnull=True, + id__in=matched_ids, + ) if documents.count() > 0: documents = prefilter_documents_by_workflowtrigger( diff --git a/src/documents/tests/test_workflows.py b/src/documents/tests/test_workflows.py index 55bad6b2c..ca5be444b 100644 --- a/src/documents/tests/test_workflows.py +++ b/src/documents/tests/test_workflows.py @@ -1742,6 +1742,48 @@ class TestWorkflows( self.assertEqual(doc.title, "Doc {created_year]") + def test_document_updated_workflow_ignores_version_documents(self) -> None: + trigger = WorkflowTrigger.objects.create( + type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED, + ) + action = WorkflowAction.objects.create( + assign_title="Doc assign owner", + assign_owner=self.user2, + ) + workflow = Workflow.objects.create( + name="Workflow 1", + order=0, + ) + workflow.triggers.add(trigger) + workflow.actions.add(action) + + root_doc = Document.objects.create( + title="root", + correspondent=self.c, + original_filename="root.pdf", + ) + version_doc = Document.objects.create( + title="version", + correspondent=self.c, + original_filename="version.pdf", + root_document=root_doc, + ) + + run_workflows(WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED, version_doc) + + root_doc.refresh_from_db() + version_doc.refresh_from_db() + + self.assertIsNone(root_doc.owner) + self.assertIsNone(version_doc.owner) + self.assertFalse( + WorkflowRun.objects.filter( + workflow=workflow, + type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED, + document=version_doc, + ).exists(), + ) + def test_document_updated_workflow(self) -> None: trigger = WorkflowTrigger.objects.create( type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED, @@ -2010,6 +2052,60 @@ class TestWorkflows( doc.refresh_from_db() self.assertEqual(doc.owner, self.user2) + def test_workflow_scheduled_trigger_ignores_version_documents(self) -> None: + trigger = WorkflowTrigger.objects.create( + type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED, + schedule_offset_days=1, + schedule_date_field=WorkflowTrigger.ScheduleDateField.ADDED, + ) + action = WorkflowAction.objects.create( + assign_title="Doc assign owner", + assign_owner=self.user2, + ) + workflow = Workflow.objects.create( + name="Workflow 1", + order=0, + ) + workflow.triggers.add(trigger) + workflow.actions.add(action) + + root_doc = Document.objects.create( + title="root", + correspondent=self.c, + original_filename="root.pdf", + added=timezone.now() - timedelta(days=10), + ) + version_doc = Document.objects.create( + title="version", + correspondent=self.c, + original_filename="version.pdf", + root_document=root_doc, + added=timezone.now() - timedelta(days=10), + ) + + tasks.check_scheduled_workflows() + + root_doc.refresh_from_db() + version_doc.refresh_from_db() + + self.assertEqual(root_doc.owner, self.user2) + self.assertIsNone(version_doc.owner) + self.assertEqual( + WorkflowRun.objects.filter( + workflow=workflow, + type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED, + document=root_doc, + ).count(), + 1, + ) + self.assertFalse( + WorkflowRun.objects.filter( + workflow=workflow, + type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED, + document=version_doc, + ).exists(), + ) + @mock.patch("documents.models.Document.objects.filter", autospec=True) def test_workflow_scheduled_trigger_modified(self, mock_filter) -> None: """ diff --git a/src/documents/views.py b/src/documents/views.py index 27d343212..a367ef881 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -1758,6 +1758,11 @@ class DocumentViewSet( .order_by("-id") .first() ) + + document_updated.send( + sender=self.__class__, + document=root_doc, + ) return Response( { "result": "OK", @@ -1827,6 +1832,11 @@ class DocumentViewSet( }, ) + document_updated.send( + sender=self.__class__, + document=root_doc, + ) + return Response( { "id": version_doc.id,