From d24fcb92b7f0b9b829731ec47a51eb39b8d20b9e Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 10 Aug 2026 19:40:40 -0700 Subject: [PATCH] Show these in tasks --- ...024_workflowaction_apply_ai_suggestions.py | 25 +++++++++++++++++++ src/documents/models.py | 1 + src/documents/signals/handlers.py | 14 ++++++++++- src/documents/tests/test_task_signals.py | 19 ++++++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/documents/migrations/0024_workflowaction_apply_ai_suggestions.py b/src/documents/migrations/0024_workflowaction_apply_ai_suggestions.py index 3a8ba6a25..560741b6b 100644 --- a/src/documents/migrations/0024_workflowaction_apply_ai_suggestions.py +++ b/src/documents/migrations/0024_workflowaction_apply_ai_suggestions.py @@ -56,4 +56,29 @@ class Migration(migrations.Migration): verbose_name="Workflow Action Type", ), ), + migrations.AlterField( + model_name="paperlesstask", + name="task_type", + field=models.CharField( + choices=[ + ("consume_file", "Consume File"), + ("train_classifier", "Train Classifier"), + ("sanity_check", "Sanity Check"), + ("index_optimize", "Index Optimize"), + ("mail_fetch", "Mail Fetch"), + ("llm_index", "LLM Index"), + ("empty_trash", "Empty Trash"), + ("check_workflows", "Check Workflows"), + ("bulk_update", "Bulk Update"), + ("reprocess_document", "Reprocess Document"), + ("build_share_link", "Build Share Link"), + ("bulk_delete", "Bulk Delete"), + ("apply_ai_suggestions", "Apply AI Suggestions"), + ], + db_index=True, + help_text="The kind of work being performed", + max_length=50, + verbose_name="Task Type", + ), + ), ] diff --git a/src/documents/models.py b/src/documents/models.py index 836fb5cf8..e0a874787 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -695,6 +695,7 @@ class PaperlessTask(ModelWithOwner): REPROCESS_DOCUMENT = "reprocess_document", _("Reprocess Document") BUILD_SHARE_LINK = "build_share_link", _("Build Share Link") BULK_DELETE = "bulk_delete", _("Bulk Delete") + APPLY_AI_SUGGESTIONS = "apply_ai_suggestions", _("Apply AI Suggestions") COMPLETE_STATUSES = ( Status.SUCCESS, diff --git a/src/documents/signals/handlers.py b/src/documents/signals/handlers.py index 748abfd00..4c6ee047b 100644 --- a/src/documents/signals/handlers.py +++ b/src/documents/signals/handlers.py @@ -998,7 +998,12 @@ def run_workflows( # Queued rather than run sync from documents.tasks import apply_ai_suggestions - apply_ai_suggestions.delay(action.pk, document.pk) + # kwargs so the PaperlessTask record can note the + # document, see _extract_input_data + apply_ai_suggestions.delay( + action_id=action.pk, + document_id=document.pk, + ) if not use_overrides: # limit title to 128 characters @@ -1054,6 +1059,7 @@ TRACKED_TASKS: dict[str, PaperlessTask.TaskType] = { "documents.tasks.update_document_content_maybe_archive_file": PaperlessTask.TaskType.REPROCESS_DOCUMENT, "documents.tasks.build_share_link_bundle": PaperlessTask.TaskType.BUILD_SHARE_LINK, "documents.bulk_edit.delete": PaperlessTask.TaskType.BULK_DELETE, + "documents.tasks.apply_ai_suggestions": PaperlessTask.TaskType.APPLY_AI_SUGGESTIONS, } _CELERY_STATE_TO_STATUS: dict[str, PaperlessTask.Status] = { @@ -1107,6 +1113,12 @@ def _extract_input_data( return {"account_ids": account_ids} return {} + if task_type == PaperlessTask.TaskType.APPLY_AI_SUGGESTIONS: + document_id = task_kwargs.get("document_id") + if document_id is not None: + return {"document_id": document_id} + return {} + return {} diff --git a/src/documents/tests/test_task_signals.py b/src/documents/tests/test_task_signals.py index 83652b5df..5aded2d17 100644 --- a/src/documents/tests/test_task_signals.py +++ b/src/documents/tests/test_task_signals.py @@ -385,6 +385,25 @@ class TestTaskFailureHandler: task_failure_handler(task_id=None, exception=ValueError("x"), traceback=None) +@pytest.mark.django_db +class TestApplyAiSuggestionsTracking: + def test_records_the_document_it_is_for(self) -> None: + """ + The action queues one task per document, so the tracked record notes + which document it is for -- otherwise a bulk run is an indistinguishable + wall of identical entries in the tasks list. + """ + task_id = send_publish( + "documents.tasks.apply_ai_suggestions", + (), + {"action_id": 1, "document_id": 42}, + ) + + task = PaperlessTask.objects.get(task_id=task_id) + assert task.task_type == PaperlessTask.TaskType.APPLY_AI_SUGGESTIONS + assert task.input_data == {"document_id": 42} + + @pytest.mark.django_db class TestTaskRevokedHandler: def test_marks_task_revoked(self, mocker: pytest_mock.MockerFixture) -> None: