mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-01-14 21:54:22 -06:00
Compare commits
3 Commits
dependabot
...
feature-wf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e54bfc174 | ||
|
|
5a2084a65b | ||
|
|
d8fadbf65a |
@@ -28,7 +28,7 @@ dependencies = [
|
||||
# Only patch versions are guaranteed to not introduce breaking changes.
|
||||
"django~=5.2.5",
|
||||
"django-allauth[mfa,socialaccount]~=65.12.1",
|
||||
"django-auditlog~=3.4.1",
|
||||
"django-auditlog~=3.3.0",
|
||||
"django-cachalot~=2.8.0",
|
||||
"django-celery-results~=2.6.0",
|
||||
"django-compression-middleware~=0.5.0",
|
||||
@@ -47,7 +47,7 @@ dependencies = [
|
||||
"faiss-cpu>=1.10",
|
||||
"filelock~=3.20.0",
|
||||
"flower~=2.0.1",
|
||||
"gotenberg-client~=0.13.1",
|
||||
"gotenberg-client~=0.12.0",
|
||||
"httpx-oauth~=0.16",
|
||||
"imap-tools~=1.11.0",
|
||||
"inotifyrecursive~=0.3",
|
||||
@@ -60,7 +60,7 @@ dependencies = [
|
||||
"llama-index-llms-openai>=0.3.38",
|
||||
"llama-index-vector-stores-faiss>=0.3",
|
||||
"nltk~=3.9.1",
|
||||
"ocrmypdf~=16.13.0",
|
||||
"ocrmypdf~=16.12.0",
|
||||
"openai>=1.76",
|
||||
"pathvalidate~=3.3.1",
|
||||
"pdf2image~=1.17.0",
|
||||
@@ -91,7 +91,7 @@ optional-dependencies.postgres = [
|
||||
"psycopg[c,pool]==3.2.12",
|
||||
# Direct dependency for proper resolution of the pre-built wheels
|
||||
"psycopg-c==3.2.12",
|
||||
"psycopg-pool==3.3",
|
||||
"psycopg-pool==3.2.7",
|
||||
]
|
||||
optional-dependencies.webserver = [
|
||||
"granian[uvloop]~=2.5.1",
|
||||
@@ -126,7 +126,7 @@ testing = [
|
||||
]
|
||||
|
||||
lint = [
|
||||
"pre-commit~=4.5.1",
|
||||
"pre-commit~=4.4.0",
|
||||
"pre-commit-uv~=4.2.0",
|
||||
"ruff~=0.14.0",
|
||||
]
|
||||
|
||||
@@ -252,7 +252,7 @@ describe('WorkflowEditDialogComponent', () => {
|
||||
expect(component.object.actions.length).toEqual(2)
|
||||
})
|
||||
|
||||
it('should update order and remove ids from actions on drag n drop', () => {
|
||||
it('should update order on drag n drop', () => {
|
||||
const action1 = workflow.actions[0]
|
||||
const action2 = workflow.actions[1]
|
||||
component.object = workflow
|
||||
@@ -261,8 +261,6 @@ describe('WorkflowEditDialogComponent', () => {
|
||||
WorkflowAction[]
|
||||
>)
|
||||
expect(component.object.actions).toEqual([action2, action1])
|
||||
expect(action1.id).toBeNull()
|
||||
expect(action2.id).toBeNull()
|
||||
})
|
||||
|
||||
it('should not include auto matching in algorithms', () => {
|
||||
|
||||
@@ -1283,11 +1283,6 @@ export class WorkflowEditDialogComponent
|
||||
const actionField = this.actionFields.at(event.previousIndex)
|
||||
this.actionFields.removeAt(event.previousIndex)
|
||||
this.actionFields.insert(event.currentIndex, actionField)
|
||||
// removing id will effectively re-create the actions in this order
|
||||
this.object.actions.forEach((a) => (a.id = null))
|
||||
this.actionFields.controls.forEach((c) =>
|
||||
c.get('id').setValue(null, { emitEvent: false })
|
||||
)
|
||||
}
|
||||
|
||||
save(): void {
|
||||
|
||||
28
src/documents/migrations/1076_workflowaction_order.py
Normal file
28
src/documents/migrations/1076_workflowaction_order.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 5.2.7 on 2026-01-14 16:53
|
||||
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
from django.db.models import F
|
||||
|
||||
|
||||
def populate_action_order(apps, schema_editor):
|
||||
WorkflowAction = apps.get_model("documents", "WorkflowAction")
|
||||
WorkflowAction.objects.all().update(order=F("id"))
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "1075_alter_paperlesstask_task_name"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="workflowaction",
|
||||
name="order",
|
||||
field=models.PositiveIntegerField(default=0, verbose_name="order"),
|
||||
),
|
||||
migrations.RunPython(
|
||||
populate_action_order,
|
||||
reverse_code=migrations.RunPython.noop,
|
||||
),
|
||||
]
|
||||
@@ -1295,6 +1295,8 @@ class WorkflowAction(models.Model):
|
||||
default=WorkflowActionType.ASSIGNMENT,
|
||||
)
|
||||
|
||||
order = models.PositiveIntegerField(_("order"), default=0)
|
||||
|
||||
assign_title = models.TextField(
|
||||
_("assign title"),
|
||||
null=True,
|
||||
|
||||
@@ -2577,7 +2577,8 @@ class WorkflowSerializer(serializers.ModelSerializer):
|
||||
set_triggers.append(trigger_instance)
|
||||
|
||||
if actions is not None and actions is not serializers.empty:
|
||||
for action in actions:
|
||||
for index, action in enumerate(actions):
|
||||
action["order"] = index
|
||||
assign_tags = action.pop("assign_tags", None)
|
||||
assign_view_users = action.pop("assign_view_users", None)
|
||||
assign_view_groups = action.pop("assign_view_groups", None)
|
||||
@@ -2704,6 +2705,16 @@ class WorkflowSerializer(serializers.ModelSerializer):
|
||||
|
||||
return instance
|
||||
|
||||
def to_representation(self, instance):
|
||||
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(
|
||||
|
||||
@@ -781,7 +781,7 @@ def run_workflows(
|
||||
|
||||
if matching.document_matches_workflow(document, workflow, trigger_type):
|
||||
action: WorkflowAction
|
||||
for action in workflow.actions.all():
|
||||
for action in workflow.actions.order_by("order", "pk"):
|
||||
message = f"Applying {action} from {workflow}"
|
||||
if not use_overrides:
|
||||
logger.info(message, extra={"group": logging_group})
|
||||
|
||||
@@ -20,9 +20,6 @@ def get_workflows_for_trigger(
|
||||
wrap it in a list; otherwise fetch enabled workflows for the trigger with
|
||||
the prefetches used by the runner.
|
||||
"""
|
||||
if workflow_to_run is not None:
|
||||
return [workflow_to_run]
|
||||
|
||||
annotated_actions = (
|
||||
WorkflowAction.objects.select_related(
|
||||
"assign_correspondent",
|
||||
@@ -105,10 +102,25 @@ def get_workflows_for_trigger(
|
||||
)
|
||||
)
|
||||
|
||||
action_prefetch = Prefetch(
|
||||
"actions",
|
||||
queryset=annotated_actions.order_by("order", "pk"),
|
||||
)
|
||||
|
||||
if workflow_to_run is not None:
|
||||
return (
|
||||
Workflow.objects.filter(pk=workflow_to_run.pk)
|
||||
.prefetch_related(
|
||||
action_prefetch,
|
||||
"triggers",
|
||||
)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
return (
|
||||
Workflow.objects.filter(enabled=True, triggers__type=trigger_type)
|
||||
.prefetch_related(
|
||||
Prefetch("actions", queryset=annotated_actions),
|
||||
action_prefetch,
|
||||
"triggers",
|
||||
)
|
||||
.order_by("order")
|
||||
|
||||
@@ -11,12 +11,14 @@ from paperless_ai.chat import stream_chat_with_documents
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_embed_model():
|
||||
from llama_index.core import settings as llama_settings
|
||||
from llama_index.core.embeddings.utils import MockEmbedding
|
||||
|
||||
mock_embed_model = MockEmbedding(embed_dim=8)
|
||||
llama_settings.Settings.embed_model = mock_embed_model
|
||||
mock_embed_model = MagicMock()
|
||||
mock_embed_model._get_text_embedding_batch.return_value = [
|
||||
[0.1] * 1536,
|
||||
] # 1 vector per input
|
||||
llama_settings.Settings._embed_model = mock_embed_model
|
||||
yield
|
||||
llama_settings.Settings.embed_model = None
|
||||
llama_settings.Settings._embed_model = None
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
||||
Reference in New Issue
Block a user