@shared_task
def check_scheduled_workflows():
+ """
+ Check and run all enabled scheduled workflows.
+
+ Scheduled triggers are evaluated based on a target date field (e.g. added, created, modified, or a custom date field),
+ combined with a day offset.
+
+ The offset is mathematically negated resulting in the following behavior:
+ - Positive offsets mean the workflow should trigger BEFORE the specified date (e.g., offset = +7 → trigger 7 days before)
+ - Negative offsets mean the workflow should trigger AFTER the specified date (e.g., offset = -7 → trigger 7 days after)
+
+ Once a document satisfies this condition, and recurring/non-recurring constraints are met, the workflow is run.
+ """
scheduled_workflows: list[Workflow] = (
Workflow.objects.filter(
triggers__type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
doc.refresh_from_db()
self.assertIsNone(doc.owner)
- def test_workflow_scheduled_trigger_negative_offset(self):
+ def test_workflow_scheduled_trigger_negative_offset_customfield(self):
"""
GIVEN:
- Existing workflow with SCHEDULED trigger and negative offset of -7 days (so 7 days after date)
doc.refresh_from_db()
self.assertEqual(doc.owner, self.user2)
+ def test_workflow_scheduled_trigger_negative_offset_created(self):
+ """
+ GIVEN:
+ - Existing workflow with SCHEDULED trigger and negative offset of -7 days (so 7 days after date)
+ - Created date set to 8 days ago → trigger time = 1 day ago and 5 days ago
+ WHEN:
+ - Scheduled workflows are checked for document
+ THEN:
+ - Workflow runs and document owner is updated for the first document, not the second
+ """
+ trigger = WorkflowTrigger.objects.create(
+ type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
+ schedule_offset_days=-7,
+ schedule_date_field=WorkflowTrigger.ScheduleDateField.CREATED,
+ )
+ action = WorkflowAction.objects.create(
+ assign_title="Doc assign owner",
+ assign_owner=self.user2,
+ )
+ w = Workflow.objects.create(
+ name="Workflow 1",
+ order=0,
+ )
+ w.triggers.add(trigger)
+ w.actions.add(action)
+ w.save()
+
+ doc = Document.objects.create(
+ title="sample test",
+ correspondent=self.c,
+ original_filename="sample.pdf",
+ checksum="1",
+ created=timezone.now().date() - timedelta(days=8),
+ )
+
+ doc2 = Document.objects.create(
+ title="sample test 2",
+ correspondent=self.c,
+ original_filename="sample2.pdf",
+ checksum="2",
+ created=timezone.now().date() - timedelta(days=5),
+ )
+
+ tasks.check_scheduled_workflows()
+ doc.refresh_from_db()
+ self.assertEqual(doc.owner, self.user2)
+ doc2.refresh_from_db()
+ self.assertIsNone(doc2.owner) # has not triggered yet
+
def test_workflow_enabled_disabled(self):
trigger = WorkflowTrigger.objects.create(
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_ADDED,