From 3c3377799c8bcac2da76a0da8aa2722aeaad166c Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Tue, 19 Aug 2025 01:16:16 -0700 Subject: [PATCH] Auto-handle parent tags in tag update --- src/documents/tests/test_tag_hierarchy.py | 14 ++++++++++ src/documents/views.py | 33 +++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/documents/tests/test_tag_hierarchy.py b/src/documents/tests/test_tag_hierarchy.py index 525ebae26..bb5b05ab9 100644 --- a/src/documents/tests/test_tag_hierarchy.py +++ b/src/documents/tests/test_tag_hierarchy.py @@ -90,3 +90,17 @@ class TestTagHierarchy(APITestCase): run_workflows(trigger.type, self.document) self.document.refresh_from_db() assert self.document.tags.count() == 0 + + def test_tag_view_parent_update_adds_parent_to_docs(self): + orphan = Tag.objects.create(name="Orphan") + self.document.tags.add(orphan) + + self.client.patch( + f"/api/tags/{orphan.pk}/", + {"parent": self.parent.pk}, + format="json", + ) + + self.document.refresh_from_db() + tags = set(self.document.tags.values_list("pk", flat=True)) + assert tags == {self.parent.pk, orphan.pk} diff --git a/src/documents/views.py b/src/documents/views.py index 111df9f2f..bfb967134 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -341,6 +341,39 @@ class TagViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin): filterset_class = TagFilterSet ordering_fields = ("color", "name", "matching_algorithm", "match", "document_count") + def perform_update(self, serializer): + old_parent = self.get_object().parent + tag = serializer.save() + new_parent = tag.parent + if old_parent != new_parent: + self._update_document_parent_tags(tag, old_parent, new_parent) + + def _update_document_parent_tags(self, tag, old_parent, new_parent): + DocumentTagRelationship = Document.tags.through + doc_ids = list(Document.objects.filter(tags=tag).values_list("pk", flat=True)) + affected = set() + + if new_parent: + parents_to_add = [new_parent, *new_parent.get_all_ancestors()] + to_create = [] + for parent in parents_to_add: + missing = Document.objects.filter(id__in=doc_ids).exclude(tags=parent) + to_create.extend( + DocumentTagRelationship(document_id=doc_id, tag_id=parent.id) + for doc_id in missing.values_list("pk", flat=True) + ) + affected.update(missing.values_list("pk", flat=True)) + if to_create: + DocumentTagRelationship.objects.bulk_create( + to_create, + ignore_conflicts=True, + ) + + if affected: + from documents.tasks import bulk_update_documents + + bulk_update_documents.delay(document_ids=list(affected)) + @extend_schema_view(**generate_object_with_permissions_schema(DocumentTypeSerializer)) class DocumentTypeViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin):