mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-30 18:27:45 -05:00
Refactor
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.1 on 2024-10-24 04:03
|
||||
# Generated by Django 5.1.1 on 2024-10-24 04:15
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
@@ -14,29 +14,18 @@ class Migration(migrations.Migration):
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="workflowtrigger",
|
||||
name="schedule_delay",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="The delay before the scheduled trigger is activated.",
|
||||
max_length=256,
|
||||
null=True,
|
||||
verbose_name="schedule delay",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="workflowtrigger",
|
||||
name="schedule_delay_custom_field",
|
||||
name="schedule_date_custom_field",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="documents.customfield",
|
||||
verbose_name="schedule delay custom field",
|
||||
verbose_name="schedule date custom field",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="workflowtrigger",
|
||||
name="schedule_delay_field",
|
||||
name="schedule_date_field",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("added", "Added"),
|
||||
@@ -45,9 +34,9 @@ class Migration(migrations.Migration):
|
||||
("custom_field", "Custom Field"),
|
||||
],
|
||||
default="added",
|
||||
help_text="The field to use for the delay.",
|
||||
help_text="The field to check for a schedule trigger.",
|
||||
max_length=20,
|
||||
verbose_name="schedule delay field",
|
||||
verbose_name="schedule date field",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
@@ -59,6 +48,15 @@ class Migration(migrations.Migration):
|
||||
verbose_name="schedule is recurring",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="workflowtrigger",
|
||||
name="schedule_offset_days",
|
||||
field=models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of days to offset the schedule trigger by.",
|
||||
verbose_name="schedule offset days",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="workflowtrigger",
|
||||
name="type",
|
||||
@@ -85,6 +83,19 @@ class Migration(migrations.Migration):
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"type",
|
||||
models.PositiveIntegerField(
|
||||
choices=[
|
||||
(1, "Consumption Started"),
|
||||
(2, "Document Added"),
|
||||
(3, "Document Updated"),
|
||||
(4, "Scheduled"),
|
||||
],
|
||||
null=True,
|
||||
verbose_name="workflow trigger type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"run_at",
|
||||
models.DateTimeField(
|
@@ -1023,7 +1023,7 @@ class WorkflowTrigger(models.Model):
|
||||
API_UPLOAD = DocumentSource.ApiUpload.value, _("Api Upload")
|
||||
MAIL_FETCH = DocumentSource.MailFetch.value, _("Mail Fetch")
|
||||
|
||||
class ScheduleDelayField(models.TextChoices):
|
||||
class ScheduleDateField(models.TextChoices):
|
||||
ADDED = "added", _("Added")
|
||||
CREATED = "created", _("Created")
|
||||
MODIFIED = "modified", _("Modified")
|
||||
@@ -1105,13 +1105,11 @@ class WorkflowTrigger(models.Model):
|
||||
verbose_name=_("has this correspondent"),
|
||||
)
|
||||
|
||||
schedule_delay = models.CharField(
|
||||
_("schedule delay"),
|
||||
max_length=256,
|
||||
null=True,
|
||||
blank=True,
|
||||
schedule_offset_days = models.PositiveIntegerField(
|
||||
_("schedule offset days"),
|
||||
default=0,
|
||||
help_text=_(
|
||||
"The delay before the scheduled trigger is activated.",
|
||||
"The number of days to offset the schedule trigger by.",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1123,22 +1121,22 @@ class WorkflowTrigger(models.Model):
|
||||
),
|
||||
)
|
||||
|
||||
schedule_delay_field = models.CharField(
|
||||
_("schedule delay field"),
|
||||
schedule_date_field = models.CharField(
|
||||
_("schedule date field"),
|
||||
max_length=20,
|
||||
choices=ScheduleDelayField.choices,
|
||||
default=ScheduleDelayField.ADDED,
|
||||
choices=ScheduleDateField.choices,
|
||||
default=ScheduleDateField.ADDED,
|
||||
help_text=_(
|
||||
"The field to use for the delay.",
|
||||
"The field to check for a schedule trigger.",
|
||||
),
|
||||
)
|
||||
|
||||
schedule_delay_custom_field = models.ForeignKey(
|
||||
schedule_date_custom_field = models.ForeignKey(
|
||||
CustomField,
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_("schedule delay custom field"),
|
||||
verbose_name=_("schedule date custom field"),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@@ -1401,6 +1399,12 @@ class WorkflowRun(models.Model):
|
||||
verbose_name=_("workflow"),
|
||||
)
|
||||
|
||||
type = models.PositiveIntegerField(
|
||||
_("workflow trigger type"),
|
||||
choices=WorkflowTrigger.WorkflowTriggerType.choices,
|
||||
null=True,
|
||||
)
|
||||
|
||||
document = models.ForeignKey(
|
||||
Document,
|
||||
null=True,
|
||||
|
@@ -21,7 +21,6 @@ from django.utils.crypto import get_random_string
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import gettext as _
|
||||
from drf_writable_nested.serializers import NestedUpdateMixin
|
||||
from duration_parser import parse_timedelta
|
||||
from guardian.core import ObjectPermissionChecker
|
||||
from guardian.shortcuts import get_users_with_perms
|
||||
from guardian.utils import get_group_obj_perms_model
|
||||
@@ -1753,22 +1752,12 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer):
|
||||
"filter_has_tags",
|
||||
"filter_has_correspondent",
|
||||
"filter_has_document_type",
|
||||
"schedule_delay",
|
||||
"schedule_offset_days",
|
||||
"schedule_is_recurring",
|
||||
"schedule_delay_field",
|
||||
"schedule_delay_custom_field",
|
||||
"schedule_date_field",
|
||||
"schedule_date_custom_field",
|
||||
]
|
||||
|
||||
def validate_schedule_delay(self, value):
|
||||
if value is not None:
|
||||
try:
|
||||
parse_timedelta(value)
|
||||
except Exception as e:
|
||||
raise serializers.ValidationError(
|
||||
f"Invalid schedule delay format: {e}",
|
||||
)
|
||||
return value
|
||||
|
||||
def validate(self, attrs):
|
||||
# Empty strings treated as None to avoid unexpected behavior
|
||||
if (
|
||||
@@ -1794,11 +1783,6 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer):
|
||||
"File name, path or mail rule filter are required",
|
||||
)
|
||||
|
||||
if attrs["type"] == WorkflowTrigger.WorkflowTriggerType.SCHEDULED and (
|
||||
"schedule_delay" not in attrs or attrs["schedule_delay"] is None
|
||||
):
|
||||
raise serializers.ValidationError("Schedule delay is required")
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
|
@@ -918,6 +918,7 @@ def run_workflows(
|
||||
|
||||
WorkflowRun.objects.create(
|
||||
workflow=workflow,
|
||||
type=trigger_type,
|
||||
document=document if not use_overrides else None,
|
||||
)
|
||||
|
||||
|
@@ -14,7 +14,6 @@ from django.db import models
|
||||
from django.db import transaction
|
||||
from django.db.models.signals import post_save
|
||||
from django.utils import timezone
|
||||
from duration_parser import parse_timedelta
|
||||
from filelock import FileLock
|
||||
from whoosh.writing import AsyncWriter
|
||||
|
||||
@@ -342,38 +341,38 @@ def check_scheduled_workflows():
|
||||
trigger: WorkflowTrigger
|
||||
for trigger in schedule_triggers:
|
||||
documents = Document.objects.none()
|
||||
delay_td = parse_timedelta(trigger.schedule_delay)
|
||||
offset_td = timedelta(days=trigger.schedule_offset_days)
|
||||
logger.debug(
|
||||
f"Checking trigger {trigger} with delay {delay_td} against field: {trigger.schedule_delay_field}",
|
||||
f"Checking trigger {trigger} with offset {offset_td} against field: {trigger.schedule_date_field}",
|
||||
)
|
||||
if (
|
||||
trigger.schedule_delay_field
|
||||
== WorkflowTrigger.ScheduleDelayField.ADDED
|
||||
trigger.schedule_date_field
|
||||
== WorkflowTrigger.ScheduleDateField.ADDED
|
||||
):
|
||||
documents = Document.objects.filter(
|
||||
added__lt=timezone.now() - delay_td,
|
||||
added__lt=timezone.now() - offset_td,
|
||||
)
|
||||
elif (
|
||||
trigger.schedule_delay_field
|
||||
== WorkflowTrigger.ScheduleDelayField.CREATED
|
||||
trigger.schedule_date_field
|
||||
== WorkflowTrigger.ScheduleDateField.CREATED
|
||||
):
|
||||
documents = Document.objects.filter(
|
||||
created__lt=timezone.now() - delay_td,
|
||||
created__lt=timezone.now() - offset_td,
|
||||
)
|
||||
elif (
|
||||
trigger.schedule_delay_field
|
||||
== WorkflowTrigger.ScheduleDelayField.MODIFIED
|
||||
trigger.schedule_date_field
|
||||
== WorkflowTrigger.ScheduleDateField.MODIFIED
|
||||
):
|
||||
documents = Document.objects.filter(
|
||||
modified__lt=timezone.now() - delay_td,
|
||||
modified__lt=timezone.now() - offset_td,
|
||||
)
|
||||
elif (
|
||||
trigger.schedule_delay_field
|
||||
== WorkflowTrigger.ScheduleDelayField.CUSTOM_FIELD
|
||||
trigger.schedule_date_field
|
||||
== WorkflowTrigger.ScheduleDateField.CUSTOM_FIELD
|
||||
):
|
||||
cf_instances = CustomFieldInstance.objects.filter(
|
||||
field=trigger.schedule_delay_custom_field,
|
||||
value_date__lt=timezone.now() - delay_td,
|
||||
field=trigger.schedule_date_custom_field,
|
||||
value_date__lt=timezone.now() - offset_td,
|
||||
)
|
||||
documents = Document.objects.filter(
|
||||
id__in=cf_instances.values_list("document", flat=True),
|
||||
@@ -385,6 +384,7 @@ def check_scheduled_workflows():
|
||||
for document in documents:
|
||||
workflow_runs = WorkflowRun.objects.filter(
|
||||
document=document,
|
||||
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
||||
workflow=workflow,
|
||||
)
|
||||
if not trigger.schedule_is_recurring and workflow_runs.exists():
|
||||
@@ -396,7 +396,7 @@ def check_scheduled_workflows():
|
||||
elif (
|
||||
trigger.schedule_is_recurring
|
||||
and workflow_runs.exists()
|
||||
and workflow_runs.last().run_at > timezone.now() - delay_td
|
||||
and workflow_runs.last().run_at > timezone.now() - offset_td
|
||||
):
|
||||
# schedule is recurring but the last run was within the delay
|
||||
logger.debug(
|
||||
|
@@ -1318,8 +1318,8 @@ class TestWorkflows(DirectoriesMixin, FileSystemAssertsMixin, APITestCase):
|
||||
"""
|
||||
trigger = WorkflowTrigger.objects.create(
|
||||
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
||||
schedule_delay="1 day",
|
||||
schedule_delay_field="created",
|
||||
schedule_offset_days=1,
|
||||
schedule_date_field="created",
|
||||
)
|
||||
action = WorkflowAction.objects.create(
|
||||
assign_title="Doc assign owner",
|
||||
@@ -1359,8 +1359,8 @@ class TestWorkflows(DirectoriesMixin, FileSystemAssertsMixin, APITestCase):
|
||||
"""
|
||||
trigger = WorkflowTrigger.objects.create(
|
||||
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
||||
schedule_delay="1 day",
|
||||
schedule_delay_field=WorkflowTrigger.ScheduleDelayField.ADDED,
|
||||
schedule_offset_days=1,
|
||||
schedule_date_field=WorkflowTrigger.ScheduleDateField.ADDED,
|
||||
)
|
||||
action = WorkflowAction.objects.create(
|
||||
assign_title="Doc assign owner",
|
||||
@@ -1402,8 +1402,8 @@ class TestWorkflows(DirectoriesMixin, FileSystemAssertsMixin, APITestCase):
|
||||
mock_filter.return_value = Document.objects.all()
|
||||
trigger = WorkflowTrigger.objects.create(
|
||||
type=WorkflowTrigger.WorkflowTriggerType.SCHEDULED,
|
||||
schedule_delay="1 day",
|
||||
schedule_delay_field=WorkflowTrigger.ScheduleDelayField.MODIFIED,
|
||||
schedule_offset_days=1,
|
||||
schedule_date_field=WorkflowTrigger.ScheduleDateField.MODIFIED,
|
||||
)
|
||||
action = WorkflowAction.objects.create(
|
||||
assign_title="Doc assign owner",
|
||||
|
Reference in New Issue
Block a user