mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 03:16:10 -06:00 
			
		
		
		
	Rename comments --> notes
This commit is contained in:
		@@ -4,6 +4,7 @@ from guardian.admin import GuardedModelAdmin
 | 
			
		||||
from .models import Correspondent
 | 
			
		||||
from .models import Document
 | 
			
		||||
from .models import DocumentType
 | 
			
		||||
from .models import Note
 | 
			
		||||
from .models import PaperlessTask
 | 
			
		||||
from .models import SavedView
 | 
			
		||||
from .models import SavedViewFilterRule
 | 
			
		||||
@@ -131,6 +132,13 @@ class TaskAdmin(admin.ModelAdmin):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NotesAdmin(GuardedModelAdmin):
 | 
			
		||||
 | 
			
		||||
    list_display = ("user", "created", "note", "document")
 | 
			
		||||
    list_filter = ("created", "user")
 | 
			
		||||
    list_display_links = ("created",)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
admin.site.register(Correspondent, CorrespondentAdmin)
 | 
			
		||||
admin.site.register(Tag, TagAdmin)
 | 
			
		||||
admin.site.register(DocumentType, DocumentTypeAdmin)
 | 
			
		||||
@@ -138,3 +146,4 @@ admin.site.register(Document, DocumentAdmin)
 | 
			
		||||
admin.site.register(SavedView, SavedViewAdmin)
 | 
			
		||||
admin.site.register(StoragePath, StoragePathAdmin)
 | 
			
		||||
admin.site.register(PaperlessTask, TaskAdmin)
 | 
			
		||||
admin.site.register(Note, NotesAdmin)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ from contextlib import contextmanager
 | 
			
		||||
from dateutil.parser import isoparse
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from documents.models import Comment
 | 
			
		||||
from documents.models import Document
 | 
			
		||||
from documents.models import Note
 | 
			
		||||
from guardian.shortcuts import get_users_with_perms
 | 
			
		||||
from whoosh import classify
 | 
			
		||||
from whoosh import highlight
 | 
			
		||||
@@ -52,7 +52,7 @@ def get_schema():
 | 
			
		||||
        path=TEXT(sortable=True),
 | 
			
		||||
        path_id=NUMERIC(),
 | 
			
		||||
        has_path=BOOLEAN(),
 | 
			
		||||
        comments=TEXT(),
 | 
			
		||||
        notes=TEXT(),
 | 
			
		||||
        owner=TEXT(),
 | 
			
		||||
        owner_id=NUMERIC(),
 | 
			
		||||
        has_owner=BOOLEAN(),
 | 
			
		||||
@@ -98,7 +98,7 @@ def open_index_searcher():
 | 
			
		||||
def update_document(writer: AsyncWriter, doc: Document):
 | 
			
		||||
    tags = ",".join([t.name for t in doc.tags.all()])
 | 
			
		||||
    tags_ids = ",".join([str(t.id) for t in doc.tags.all()])
 | 
			
		||||
    comments = ",".join([str(c.comment) for c in Comment.objects.filter(document=doc)])
 | 
			
		||||
    notes = ",".join([str(c.note) for c in Note.objects.filter(document=doc)])
 | 
			
		||||
    asn = doc.archive_serial_number
 | 
			
		||||
    if asn is not None and (
 | 
			
		||||
        asn < Document.ARCHIVE_SERIAL_NUMBER_MIN
 | 
			
		||||
@@ -136,7 +136,7 @@ def update_document(writer: AsyncWriter, doc: Document):
 | 
			
		||||
        path=doc.storage_path.name if doc.storage_path else None,
 | 
			
		||||
        path_id=doc.storage_path.id if doc.storage_path else None,
 | 
			
		||||
        has_path=doc.storage_path is not None,
 | 
			
		||||
        comments=comments,
 | 
			
		||||
        notes=notes,
 | 
			
		||||
        owner=doc.owner.username if doc.owner else None,
 | 
			
		||||
        owner_id=doc.owner.id if doc.owner else None,
 | 
			
		||||
        has_owner=doc.owner is not None,
 | 
			
		||||
@@ -293,7 +293,7 @@ class DelayedFullTextQuery(DelayedQuery):
 | 
			
		||||
    def _get_query(self):
 | 
			
		||||
        q_str = self.query_params["query"]
 | 
			
		||||
        qp = MultifieldParser(
 | 
			
		||||
            ["content", "title", "correspondent", "tag", "type", "comments"],
 | 
			
		||||
            ["content", "title", "correspondent", "tag", "type", "notes"],
 | 
			
		||||
            self.searcher.ixreader.schema,
 | 
			
		||||
        )
 | 
			
		||||
        qp.add_plugin(DateParserPlugin(basedate=timezone.now()))
 | 
			
		||||
 
 | 
			
		||||
@@ -17,10 +17,10 @@ from django.core.management.base import BaseCommand
 | 
			
		||||
from django.core.management.base import CommandError
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from documents.models import Comment
 | 
			
		||||
from documents.models import Correspondent
 | 
			
		||||
from documents.models import Document
 | 
			
		||||
from documents.models import DocumentType
 | 
			
		||||
from documents.models import Note
 | 
			
		||||
from documents.models import SavedView
 | 
			
		||||
from documents.models import SavedViewFilterRule
 | 
			
		||||
from documents.models import StoragePath
 | 
			
		||||
@@ -206,7 +206,7 @@ class Command(BaseCommand):
 | 
			
		||||
                self.files_in_export_dir.add(x.resolve())
 | 
			
		||||
 | 
			
		||||
        # 2. Create manifest, containing all correspondents, types, tags, storage paths
 | 
			
		||||
        # comments, documents and ui_settings
 | 
			
		||||
        # note, documents and ui_settings
 | 
			
		||||
        with transaction.atomic():
 | 
			
		||||
            manifest = json.loads(
 | 
			
		||||
                serializers.serialize("json", Correspondent.objects.all()),
 | 
			
		||||
@@ -222,11 +222,11 @@ class Command(BaseCommand):
 | 
			
		||||
                serializers.serialize("json", StoragePath.objects.all()),
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            comments = json.loads(
 | 
			
		||||
                serializers.serialize("json", Comment.objects.all()),
 | 
			
		||||
            notes = json.loads(
 | 
			
		||||
                serializers.serialize("json", Note.objects.all()),
 | 
			
		||||
            )
 | 
			
		||||
            if not self.split_manifest:
 | 
			
		||||
                manifest += comments
 | 
			
		||||
                manifest += notes
 | 
			
		||||
 | 
			
		||||
            documents = Document.objects.order_by("id")
 | 
			
		||||
            document_map = {d.pk: d for d in documents}
 | 
			
		||||
@@ -359,7 +359,7 @@ class Command(BaseCommand):
 | 
			
		||||
                content += list(
 | 
			
		||||
                    filter(
 | 
			
		||||
                        lambda d: d["fields"]["document"] == document_dict["pk"],
 | 
			
		||||
                        comments,
 | 
			
		||||
                        notes,
 | 
			
		||||
                    ),
 | 
			
		||||
                )
 | 
			
		||||
                manifest_name.write_text(json.dumps(content, indent=2))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
# Generated by Django 4.1.5 on 2023-03-17 21:23
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
 | 
			
		||||
        ("documents", "1033_alter_documenttype_options_alter_tag_options_and_more"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="comment",
 | 
			
		||||
            name="document",
 | 
			
		||||
            field=models.ForeignKey(
 | 
			
		||||
                blank=True,
 | 
			
		||||
                null=True,
 | 
			
		||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                related_name="comments",
 | 
			
		||||
                to="documents.document",
 | 
			
		||||
                verbose_name="document",
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="comment",
 | 
			
		||||
            name="user",
 | 
			
		||||
            field=models.ForeignKey(
 | 
			
		||||
                blank=True,
 | 
			
		||||
                null=True,
 | 
			
		||||
                on_delete=django.db.models.deletion.SET_NULL,
 | 
			
		||||
                related_name="comments",
 | 
			
		||||
                to=settings.AUTH_USER_MODEL,
 | 
			
		||||
                verbose_name="user",
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										61
									
								
								src/documents/migrations/1035_rename_comment_note.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/documents/migrations/1035_rename_comment_note.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
# Generated by Django 4.1.5 on 2023-03-17 22:15
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
from django.db import models
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
 | 
			
		||||
        ("documents", "1034_alter_savedviewfilterrule_rule_type"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RenameModel(
 | 
			
		||||
            old_name="Comment",
 | 
			
		||||
            new_name="Note",
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RenameField(model_name="note", old_name="comment", new_name="note"),
 | 
			
		||||
        migrations.AlterModelOptions(
 | 
			
		||||
            name="note",
 | 
			
		||||
            options={
 | 
			
		||||
                "ordering": ("created",),
 | 
			
		||||
                "verbose_name": "note",
 | 
			
		||||
                "verbose_name_plural": "notes",
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="note",
 | 
			
		||||
            name="document",
 | 
			
		||||
            field=models.ForeignKey(
 | 
			
		||||
                blank=True,
 | 
			
		||||
                null=True,
 | 
			
		||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
			
		||||
                related_name="notes",
 | 
			
		||||
                to="documents.document",
 | 
			
		||||
                verbose_name="document",
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="note",
 | 
			
		||||
            name="note",
 | 
			
		||||
            field=models.TextField(
 | 
			
		||||
                blank=True, help_text="Note for the document", verbose_name="content"
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="note",
 | 
			
		||||
            name="user",
 | 
			
		||||
            field=models.ForeignKey(
 | 
			
		||||
                blank=True,
 | 
			
		||||
                null=True,
 | 
			
		||||
                on_delete=django.db.models.deletion.SET_NULL,
 | 
			
		||||
                related_name="notes",
 | 
			
		||||
                to=settings.AUTH_USER_MODEL,
 | 
			
		||||
                verbose_name="user",
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -635,11 +635,11 @@ class PaperlessTask(models.Model):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Comment(models.Model):
 | 
			
		||||
    comment = models.TextField(
 | 
			
		||||
class Note(models.Model):
 | 
			
		||||
    note = models.TextField(
 | 
			
		||||
        _("content"),
 | 
			
		||||
        blank=True,
 | 
			
		||||
        help_text=_("Comment for the document"),
 | 
			
		||||
        help_text=_("Note for the document"),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    created = models.DateTimeField(
 | 
			
		||||
@@ -652,7 +652,7 @@ class Comment(models.Model):
 | 
			
		||||
        Document,
 | 
			
		||||
        blank=True,
 | 
			
		||||
        null=True,
 | 
			
		||||
        related_name="comments",
 | 
			
		||||
        related_name="notes",
 | 
			
		||||
        on_delete=models.CASCADE,
 | 
			
		||||
        verbose_name=_("document"),
 | 
			
		||||
    )
 | 
			
		||||
@@ -661,15 +661,15 @@ class Comment(models.Model):
 | 
			
		||||
        User,
 | 
			
		||||
        blank=True,
 | 
			
		||||
        null=True,
 | 
			
		||||
        related_name="comments",
 | 
			
		||||
        related_name="notes",
 | 
			
		||||
        on_delete=models.SET_NULL,
 | 
			
		||||
        verbose_name=_("user"),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        ordering = ("created",)
 | 
			
		||||
        verbose_name = _("comment")
 | 
			
		||||
        verbose_name_plural = _("comments")
 | 
			
		||||
        verbose_name = _("note")
 | 
			
		||||
        verbose_name_plural = _("notes")
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return self.content
 | 
			
		||||
        return self.note
 | 
			
		||||
 
 | 
			
		||||
@@ -382,8 +382,6 @@ class DocumentSerializer(OwnedObjectSerializer, DynamicFieldsModelSerializer):
 | 
			
		||||
    archived_file_name = SerializerMethodField()
 | 
			
		||||
    created_date = serializers.DateField(required=False)
 | 
			
		||||
 | 
			
		||||
    num_comments = serializers.IntegerField(read_only=True)
 | 
			
		||||
 | 
			
		||||
    owner = serializers.PrimaryKeyRelatedField(
 | 
			
		||||
        queryset=User.objects.all(),
 | 
			
		||||
        required=False,
 | 
			
		||||
@@ -444,8 +442,7 @@ class DocumentSerializer(OwnedObjectSerializer, DynamicFieldsModelSerializer):
 | 
			
		||||
            "owner",
 | 
			
		||||
            "permissions",
 | 
			
		||||
            "set_permissions",
 | 
			
		||||
            "comments",
 | 
			
		||||
            "num_comments",
 | 
			
		||||
            "notes",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ from documents.models import PaperlessTask
 | 
			
		||||
from documents.models import SavedView
 | 
			
		||||
from documents.models import StoragePath
 | 
			
		||||
from documents.models import Tag
 | 
			
		||||
from documents.models import Comment
 | 
			
		||||
from documents.models import Note
 | 
			
		||||
from documents.tests.utils import DirectoriesMixin
 | 
			
		||||
from paperless import version
 | 
			
		||||
from rest_framework.test import APITestCase
 | 
			
		||||
@@ -1717,28 +1717,28 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
 | 
			
		||||
            1,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_get_existing_comments(self):
 | 
			
		||||
    def test_get_existing_notes(self):
 | 
			
		||||
        """
 | 
			
		||||
        GIVEN:
 | 
			
		||||
            - A document with a single comment
 | 
			
		||||
            - A document with a single note
 | 
			
		||||
        WHEN:
 | 
			
		||||
            - API reuqest for document comments is made
 | 
			
		||||
            - API reuqest for document notes is made
 | 
			
		||||
        THEN:
 | 
			
		||||
            - The associated comment is returned
 | 
			
		||||
            - The associated note is returned
 | 
			
		||||
        """
 | 
			
		||||
        doc = Document.objects.create(
 | 
			
		||||
            title="test",
 | 
			
		||||
            mime_type="application/pdf",
 | 
			
		||||
            content="this is a document which will have comments!",
 | 
			
		||||
            content="this is a document which will have notes!",
 | 
			
		||||
        )
 | 
			
		||||
        comment = Comment.objects.create(
 | 
			
		||||
            comment="This is a comment.",
 | 
			
		||||
        note = Note.objects.create(
 | 
			
		||||
            note="This is a note.",
 | 
			
		||||
            document=doc,
 | 
			
		||||
            user=self.user,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        response = self.client.get(
 | 
			
		||||
            f"/api/documents/{doc.pk}/comments/",
 | 
			
		||||
            f"/api/documents/{doc.pk}/notes/",
 | 
			
		||||
            format="json",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
@@ -1754,39 +1754,39 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
 | 
			
		||||
        self.assertDictEqual(
 | 
			
		||||
            resp_data,
 | 
			
		||||
            {
 | 
			
		||||
                "id": comment.id,
 | 
			
		||||
                "comment": comment.comment,
 | 
			
		||||
                "id": note.id,
 | 
			
		||||
                "note": note.note,
 | 
			
		||||
                "user": {
 | 
			
		||||
                    "id": comment.user.id,
 | 
			
		||||
                    "username": comment.user.username,
 | 
			
		||||
                    "first_name": comment.user.first_name,
 | 
			
		||||
                    "last_name": comment.user.last_name,
 | 
			
		||||
                    "id": note.user.id,
 | 
			
		||||
                    "username": note.user.username,
 | 
			
		||||
                    "first_name": note.user.first_name,
 | 
			
		||||
                    "last_name": note.user.last_name,
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_create_comment(self):
 | 
			
		||||
    def test_create_note(self):
 | 
			
		||||
        """
 | 
			
		||||
        GIVEN:
 | 
			
		||||
            - Existing document
 | 
			
		||||
        WHEN:
 | 
			
		||||
            - API request is made to add a comment
 | 
			
		||||
            - API request is made to add a note
 | 
			
		||||
        THEN:
 | 
			
		||||
            - Comment is created and associated with document
 | 
			
		||||
            - note is created and associated with document
 | 
			
		||||
        """
 | 
			
		||||
        doc = Document.objects.create(
 | 
			
		||||
            title="test",
 | 
			
		||||
            mime_type="application/pdf",
 | 
			
		||||
            content="this is a document which will have comments added",
 | 
			
		||||
            content="this is a document which will have notes added",
 | 
			
		||||
        )
 | 
			
		||||
        resp = self.client.post(
 | 
			
		||||
            f"/api/documents/{doc.pk}/comments/",
 | 
			
		||||
            data={"comment": "this is a posted comment"},
 | 
			
		||||
            f"/api/documents/{doc.pk}/notes/",
 | 
			
		||||
            data={"note": "this is a posted note"},
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
 | 
			
		||||
 | 
			
		||||
        response = self.client.get(
 | 
			
		||||
            f"/api/documents/{doc.pk}/comments/",
 | 
			
		||||
            f"/api/documents/{doc.pk}/notes/",
 | 
			
		||||
            format="json",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
@@ -1798,48 +1798,48 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
 | 
			
		||||
 | 
			
		||||
        resp_data = resp_data[0]
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(resp_data["comment"], "this is a posted comment")
 | 
			
		||||
        self.assertEqual(resp_data["note"], "this is a posted note")
 | 
			
		||||
 | 
			
		||||
    def test_delete_comment(self):
 | 
			
		||||
    def test_delete_note(self):
 | 
			
		||||
        """
 | 
			
		||||
        GIVEN:
 | 
			
		||||
            - Existing document
 | 
			
		||||
        WHEN:
 | 
			
		||||
            - API request is made to add a comment
 | 
			
		||||
            - API request is made to add a note
 | 
			
		||||
        THEN:
 | 
			
		||||
            - Comment is created and associated with document
 | 
			
		||||
            - note is created and associated with document
 | 
			
		||||
        """
 | 
			
		||||
        doc = Document.objects.create(
 | 
			
		||||
            title="test",
 | 
			
		||||
            mime_type="application/pdf",
 | 
			
		||||
            content="this is a document which will have comments!",
 | 
			
		||||
            content="this is a document which will have notes!",
 | 
			
		||||
        )
 | 
			
		||||
        comment = Comment.objects.create(
 | 
			
		||||
            comment="This is a comment.",
 | 
			
		||||
        note = Note.objects.create(
 | 
			
		||||
            note="This is a note.",
 | 
			
		||||
            document=doc,
 | 
			
		||||
            user=self.user,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        response = self.client.delete(
 | 
			
		||||
            f"/api/documents/{doc.pk}/comments/?id={comment.pk}",
 | 
			
		||||
            f"/api/documents/{doc.pk}/notes/?id={note.pk}",
 | 
			
		||||
            format="json",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(response.status_code, status.HTTP_200_OK)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(len(Comment.objects.all()), 0)
 | 
			
		||||
        self.assertEqual(len(Note.objects.all()), 0)
 | 
			
		||||
 | 
			
		||||
    def test_get_comments_no_doc(self):
 | 
			
		||||
    def test_get_notes_no_doc(self):
 | 
			
		||||
        """
 | 
			
		||||
        GIVEN:
 | 
			
		||||
            - A request to get comments from a non-existent document
 | 
			
		||||
            - A request to get notes from a non-existent document
 | 
			
		||||
        WHEN:
 | 
			
		||||
            - API request for document comments is made
 | 
			
		||||
            - API request for document notes is made
 | 
			
		||||
        THEN:
 | 
			
		||||
            - HTTP status.HTTP_404_NOT_FOUND is returned
 | 
			
		||||
        """
 | 
			
		||||
        response = self.client.get(
 | 
			
		||||
            "/api/documents/500/comments/",
 | 
			
		||||
            "/api/documents/500/notes/",
 | 
			
		||||
            format="json",
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
 | 
			
		||||
 
 | 
			
		||||
@@ -13,10 +13,10 @@ from django.test import override_settings
 | 
			
		||||
from django.test import TestCase
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from documents.management.commands import document_exporter
 | 
			
		||||
from documents.models import Comment
 | 
			
		||||
from documents.models import Correspondent
 | 
			
		||||
from documents.models import Document
 | 
			
		||||
from documents.models import DocumentType
 | 
			
		||||
from documents.models import Note
 | 
			
		||||
from documents.models import StoragePath
 | 
			
		||||
from documents.models import Tag
 | 
			
		||||
from documents.models import User
 | 
			
		||||
@@ -66,8 +66,8 @@ class TestExportImport(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
 | 
			
		||||
            storage_type=Document.STORAGE_TYPE_GPG,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.comment = Comment.objects.create(
 | 
			
		||||
            comment="This is a comment. amaze.",
 | 
			
		||||
        self.note = Note.objects.create(
 | 
			
		||||
            note="This is a note. amaze.",
 | 
			
		||||
            document=self.d1,
 | 
			
		||||
            user=self.user,
 | 
			
		||||
        )
 | 
			
		||||
@@ -199,8 +199,8 @@ class TestExportImport(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
 | 
			
		||||
                        checksum = hashlib.md5(f.read()).hexdigest()
 | 
			
		||||
                    self.assertEqual(checksum, element["fields"]["archive_checksum"])
 | 
			
		||||
 | 
			
		||||
            elif element["model"] == "documents.comment":
 | 
			
		||||
                self.assertEqual(element["fields"]["comment"], self.comment.comment)
 | 
			
		||||
            elif element["model"] == "documents.note":
 | 
			
		||||
                self.assertEqual(element["fields"]["note"], self.note.note)
 | 
			
		||||
                self.assertEqual(element["fields"]["document"], self.d1.id)
 | 
			
		||||
                self.assertEqual(element["fields"]["user"], self.user.id)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -72,10 +72,10 @@ from .matching import match_correspondents
 | 
			
		||||
from .matching import match_document_types
 | 
			
		||||
from .matching import match_storage_paths
 | 
			
		||||
from .matching import match_tags
 | 
			
		||||
from .models import Comment
 | 
			
		||||
from .models import Correspondent
 | 
			
		||||
from .models import Document
 | 
			
		||||
from .models import DocumentType
 | 
			
		||||
from .models import Note
 | 
			
		||||
from .models import PaperlessTask
 | 
			
		||||
from .models import SavedView
 | 
			
		||||
from .models import StoragePath
 | 
			
		||||
@@ -230,7 +230,7 @@ class DocumentViewSet(
 | 
			
		||||
    GenericViewSet,
 | 
			
		||||
):
 | 
			
		||||
    model = Document
 | 
			
		||||
    queryset = Document.objects.annotate(num_comments=Count("comments"))
 | 
			
		||||
    queryset = Document.objects.annotate(num_notes=Count("notes"))
 | 
			
		||||
    serializer_class = DocumentSerializer
 | 
			
		||||
    pagination_class = StandardPagination
 | 
			
		||||
    permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
 | 
			
		||||
@@ -251,11 +251,11 @@ class DocumentViewSet(
 | 
			
		||||
        "modified",
 | 
			
		||||
        "added",
 | 
			
		||||
        "archive_serial_number",
 | 
			
		||||
        "num_comments",
 | 
			
		||||
        "num_notes",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return Document.objects.distinct()
 | 
			
		||||
        return Document.objects.distinct().annotate(num_notes=Count("notes"))
 | 
			
		||||
 | 
			
		||||
    def get_serializer(self, *args, **kwargs):
 | 
			
		||||
        super().get_serializer(*args, **kwargs)
 | 
			
		||||
@@ -442,11 +442,11 @@ class DocumentViewSet(
 | 
			
		||||
        except (FileNotFoundError, Document.DoesNotExist):
 | 
			
		||||
            raise Http404()
 | 
			
		||||
 | 
			
		||||
    def getComments(self, doc):
 | 
			
		||||
    def getNotes(self, doc):
 | 
			
		||||
        return [
 | 
			
		||||
            {
 | 
			
		||||
                "id": c.id,
 | 
			
		||||
                "comment": c.comment,
 | 
			
		||||
                "note": c.note,
 | 
			
		||||
                "created": c.created,
 | 
			
		||||
                "user": {
 | 
			
		||||
                    "id": c.user.id,
 | 
			
		||||
@@ -455,11 +455,11 @@ class DocumentViewSet(
 | 
			
		||||
                    "last_name": c.user.last_name,
 | 
			
		||||
                },
 | 
			
		||||
            }
 | 
			
		||||
            for c in Comment.objects.filter(document=doc).order_by("-created")
 | 
			
		||||
            for c in Note.objects.filter(document=doc).order_by("-created")
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    @action(methods=["get", "post", "delete"], detail=True)
 | 
			
		||||
    def comments(self, request, pk=None):
 | 
			
		||||
    def notes(self, request, pk=None):
 | 
			
		||||
        try:
 | 
			
		||||
            doc = Document.objects.get(pk=pk)
 | 
			
		||||
        except Document.DoesNotExist:
 | 
			
		||||
@@ -469,17 +469,17 @@ class DocumentViewSet(
 | 
			
		||||
 | 
			
		||||
        if request.method == "GET":
 | 
			
		||||
            try:
 | 
			
		||||
                return Response(self.getComments(doc))
 | 
			
		||||
                return Response(self.getNotes(doc))
 | 
			
		||||
            except Exception as e:
 | 
			
		||||
                logger.warning(f"An error occurred retrieving comments: {str(e)}")
 | 
			
		||||
                logger.warning(f"An error occurred retrieving notes: {str(e)}")
 | 
			
		||||
                return Response(
 | 
			
		||||
                    {"error": "Error retreiving comments, check logs for more detail."},
 | 
			
		||||
                    {"error": "Error retreiving notes, check logs for more detail."},
 | 
			
		||||
                )
 | 
			
		||||
        elif request.method == "POST":
 | 
			
		||||
            try:
 | 
			
		||||
                c = Comment.objects.create(
 | 
			
		||||
                c = Note.objects.create(
 | 
			
		||||
                    document=doc,
 | 
			
		||||
                    comment=request.data["comment"],
 | 
			
		||||
                    note=request.data["note"],
 | 
			
		||||
                    user=currentUser,
 | 
			
		||||
                )
 | 
			
		||||
                c.save()
 | 
			
		||||
@@ -488,23 +488,23 @@ class DocumentViewSet(
 | 
			
		||||
 | 
			
		||||
                index.add_or_update_document(self.get_object())
 | 
			
		||||
 | 
			
		||||
                return Response(self.getComments(doc))
 | 
			
		||||
                return Response(self.getNotes(doc))
 | 
			
		||||
            except Exception as e:
 | 
			
		||||
                logger.warning(f"An error occurred saving comment: {str(e)}")
 | 
			
		||||
                logger.warning(f"An error occurred saving note: {str(e)}")
 | 
			
		||||
                return Response(
 | 
			
		||||
                    {
 | 
			
		||||
                        "error": "Error saving comment, check logs for more detail.",
 | 
			
		||||
                        "error": "Error saving note, check logs for more detail.",
 | 
			
		||||
                    },
 | 
			
		||||
                )
 | 
			
		||||
        elif request.method == "DELETE":
 | 
			
		||||
            comment = Comment.objects.get(id=int(request.GET.get("id")))
 | 
			
		||||
            comment.delete()
 | 
			
		||||
            note = Note.objects.get(id=int(request.GET.get("id")))
 | 
			
		||||
            note.delete()
 | 
			
		||||
 | 
			
		||||
            from documents import index
 | 
			
		||||
 | 
			
		||||
            index.add_or_update_document(self.get_object())
 | 
			
		||||
 | 
			
		||||
            return Response(self.getComments(doc))
 | 
			
		||||
            return Response(self.getNotes(doc))
 | 
			
		||||
 | 
			
		||||
        return Response(
 | 
			
		||||
            {
 | 
			
		||||
@@ -516,14 +516,14 @@ class DocumentViewSet(
 | 
			
		||||
class SearchResultSerializer(DocumentSerializer, PassUserMixin):
 | 
			
		||||
    def to_representation(self, instance):
 | 
			
		||||
        doc = Document.objects.get(id=instance["id"])
 | 
			
		||||
        comments = ",".join(
 | 
			
		||||
            [str(c.comment) for c in Comment.objects.filter(document=instance["id"])],
 | 
			
		||||
        notes = ",".join(
 | 
			
		||||
            [str(c.note) for c in Note.objects.filter(document=instance["id"])],
 | 
			
		||||
        )
 | 
			
		||||
        r = super().to_representation(doc)
 | 
			
		||||
        r["__search_hit__"] = {
 | 
			
		||||
            "score": instance.score,
 | 
			
		||||
            "highlights": instance.highlights("content", text=doc.content),
 | 
			
		||||
            "comment_highlights": instance.highlights("comments", text=comments)
 | 
			
		||||
            "note_highlights": instance.highlights("notes", text=notes)
 | 
			
		||||
            if doc
 | 
			
		||||
            else None,
 | 
			
		||||
            "rank": instance.rank,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user