mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-06-20 15:17:32 -05:00
Fix: restore expected pre-2.16 scheduled workflow offset behavior (#10218)
This commit is contained in:
parent
07882b918b
commit
3b069ac034
@ -408,7 +408,7 @@ Currently, there are three events that correspond to workflow trigger 'types':
|
|||||||
tags, doc type, or correspondent.
|
tags, doc type, or correspondent.
|
||||||
4. **Scheduled**: a scheduled trigger that can be used to run workflows at a specific time. The date used can be either the document
|
4. **Scheduled**: a scheduled trigger that can be used to run workflows at a specific time. The date used can be either the document
|
||||||
added, created, updated date or you can specify a (date) custom field. You can also specify a day offset from the date (positive
|
added, created, updated date or you can specify a (date) custom field. You can also specify a day offset from the date (positive
|
||||||
offsets will trigger before the date, negative offsets will trigger after).
|
offsets will trigger after the date, negative offsets will trigger before).
|
||||||
|
|
||||||
The following flow diagram illustrates the three document trigger types:
|
The following flow diagram illustrates the three document trigger types:
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@
|
|||||||
formControlName="schedule_offset_days"
|
formControlName="schedule_offset_days"
|
||||||
[showAdd]="false"
|
[showAdd]="false"
|
||||||
[error]="error?.schedule_offset_days"
|
[error]="error?.schedule_offset_days"
|
||||||
hint="Positive values will trigger the workflow before the date, negative values after."
|
hint="Positive values will trigger after the date, negative values before."
|
||||||
i18n-hint
|
i18n-hint
|
||||||
></pngx-input-number>
|
></pngx-input-number>
|
||||||
</div>
|
</div>
|
||||||
|
@ -420,7 +420,7 @@ def check_scheduled_workflows():
|
|||||||
trigger: WorkflowTrigger
|
trigger: WorkflowTrigger
|
||||||
for trigger in schedule_triggers:
|
for trigger in schedule_triggers:
|
||||||
documents = Document.objects.none()
|
documents = Document.objects.none()
|
||||||
offset_td = datetime.timedelta(days=-trigger.schedule_offset_days)
|
offset_td = datetime.timedelta(days=trigger.schedule_offset_days)
|
||||||
threshold = now - offset_td
|
threshold = now - offset_td
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Trigger {trigger.id}: checking if (date + {offset_td}) <= now ({now})",
|
f"Trigger {trigger.id}: checking if (date + {offset_td}) <= now ({now})",
|
||||||
|
@ -1614,13 +1614,14 @@ class TestWorkflows(
|
|||||||
def test_workflow_scheduled_trigger_negative_offset_customfield(self):
|
def test_workflow_scheduled_trigger_negative_offset_customfield(self):
|
||||||
"""
|
"""
|
||||||
GIVEN:
|
GIVEN:
|
||||||
- Existing workflow with SCHEDULED trigger and negative offset of -7 days (so 7 days after date)
|
- Workflow with offset -7 (i.e., 7 days *before* the date)
|
||||||
- Custom field date initially set to 5 days ago → trigger time = 2 days in future
|
- doc1: value_date = 5 days ago → trigger time = 12 days ago → triggers
|
||||||
- Then updated to 8 days ago → trigger time = 1 day ago
|
- doc2: value_date = 9 days in future → trigger time = 2 days in future → does NOT trigger
|
||||||
WHEN:
|
WHEN:
|
||||||
- Scheduled workflows are checked for document with custom field date 8 days in the past
|
- Scheduled workflows are checked
|
||||||
THEN:
|
THEN:
|
||||||
- Workflow runs and document owner is updated
|
- doc1 has owner assigned
|
||||||
|
- doc2 remains untouched
|
||||||
"""
|
"""
|
||||||
trigger = WorkflowTrigger.objects.create(
|
trigger = WorkflowTrigger.objects.create(
|
||||||
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
||||||
@ -1640,38 +1641,49 @@ class TestWorkflows(
|
|||||||
w.actions.add(action)
|
w.actions.add(action)
|
||||||
w.save()
|
w.save()
|
||||||
|
|
||||||
doc = Document.objects.create(
|
doc1 = Document.objects.create(
|
||||||
title="sample test",
|
title="doc1",
|
||||||
correspondent=self.c,
|
correspondent=self.c,
|
||||||
original_filename="sample.pdf",
|
original_filename="doc1.pdf",
|
||||||
|
checksum="doc1-checksum",
|
||||||
)
|
)
|
||||||
cfi = CustomFieldInstance.objects.create(
|
CustomFieldInstance.objects.create(
|
||||||
document=doc,
|
document=doc1,
|
||||||
field=self.cf1,
|
field=self.cf1,
|
||||||
value_date=timezone.now() - timedelta(days=5),
|
value_date=timezone.now().date() - timedelta(days=5),
|
||||||
|
)
|
||||||
|
|
||||||
|
doc2 = Document.objects.create(
|
||||||
|
title="doc2",
|
||||||
|
correspondent=self.c,
|
||||||
|
original_filename="doc2.pdf",
|
||||||
|
checksum="doc2-checksum",
|
||||||
|
)
|
||||||
|
CustomFieldInstance.objects.create(
|
||||||
|
document=doc2,
|
||||||
|
field=self.cf1,
|
||||||
|
value_date=timezone.now().date() + timedelta(days=9),
|
||||||
)
|
)
|
||||||
|
|
||||||
tasks.check_scheduled_workflows()
|
tasks.check_scheduled_workflows()
|
||||||
|
|
||||||
doc.refresh_from_db()
|
doc1.refresh_from_db()
|
||||||
self.assertIsNone(doc.owner) # has not triggered yet
|
self.assertEqual(doc1.owner, self.user2)
|
||||||
|
|
||||||
cfi.value_date = timezone.now() - timedelta(days=8)
|
doc2.refresh_from_db()
|
||||||
cfi.save()
|
self.assertIsNone(doc2.owner)
|
||||||
|
|
||||||
tasks.check_scheduled_workflows()
|
|
||||||
doc.refresh_from_db()
|
|
||||||
self.assertEqual(doc.owner, self.user2)
|
|
||||||
|
|
||||||
def test_workflow_scheduled_trigger_negative_offset_created(self):
|
def test_workflow_scheduled_trigger_negative_offset_created(self):
|
||||||
"""
|
"""
|
||||||
GIVEN:
|
GIVEN:
|
||||||
- Existing workflow with SCHEDULED trigger and negative offset of -7 days (so 7 days after date)
|
- Existing workflow with SCHEDULED trigger and negative offset of -7 days (so 7 days before date)
|
||||||
- Created date set to 8 days ago → trigger time = 1 day ago and 5 days ago
|
- doc created 8 days ago → trigger time = 15 days ago → triggers
|
||||||
|
- doc2 created 8 days *in the future* → trigger time = 1 day in future → does NOT trigger
|
||||||
WHEN:
|
WHEN:
|
||||||
- Scheduled workflows are checked for document
|
- Scheduled workflows are checked for document
|
||||||
THEN:
|
THEN:
|
||||||
- Workflow runs and document owner is updated for the first document, not the second
|
- doc is matched and owner updated
|
||||||
|
- doc2 is untouched
|
||||||
"""
|
"""
|
||||||
trigger = WorkflowTrigger.objects.create(
|
trigger = WorkflowTrigger.objects.create(
|
||||||
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
||||||
@ -1703,7 +1715,7 @@ class TestWorkflows(
|
|||||||
correspondent=self.c,
|
correspondent=self.c,
|
||||||
original_filename="sample2.pdf",
|
original_filename="sample2.pdf",
|
||||||
checksum="2",
|
checksum="2",
|
||||||
created=timezone.now().date() - timedelta(days=5),
|
created=timezone.now().date() + timedelta(days=8),
|
||||||
)
|
)
|
||||||
|
|
||||||
tasks.check_scheduled_workflows()
|
tasks.check_scheduled_workflows()
|
||||||
@ -1712,6 +1724,40 @@ class TestWorkflows(
|
|||||||
doc2.refresh_from_db()
|
doc2.refresh_from_db()
|
||||||
self.assertIsNone(doc2.owner) # has not triggered yet
|
self.assertIsNone(doc2.owner) # has not triggered yet
|
||||||
|
|
||||||
|
def test_offset_positive_means_after(self):
|
||||||
|
"""
|
||||||
|
GIVEN:
|
||||||
|
- Document created 30 days ago
|
||||||
|
- Workflow with offset +10
|
||||||
|
EXPECT:
|
||||||
|
- It triggers now, because created + 10 = 20 days ago < now
|
||||||
|
"""
|
||||||
|
doc = Document.objects.create(
|
||||||
|
title="Test doc",
|
||||||
|
created=timezone.now() - timedelta(days=30),
|
||||||
|
correspondent=self.c,
|
||||||
|
original_filename="test.pdf",
|
||||||
|
)
|
||||||
|
trigger = WorkflowTrigger.objects.create(
|
||||||
|
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
||||||
|
schedule_date_field=WorkflowTrigger.ScheduleDateField.CREATED,
|
||||||
|
schedule_offset_days=10,
|
||||||
|
)
|
||||||
|
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()
|
||||||
|
tasks.check_scheduled_workflows()
|
||||||
|
doc.refresh_from_db()
|
||||||
|
self.assertEqual(doc.owner, self.user2)
|
||||||
|
|
||||||
def test_workflow_scheduled_filters_queryset(self):
|
def test_workflow_scheduled_filters_queryset(self):
|
||||||
"""
|
"""
|
||||||
GIVEN:
|
GIVEN:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user