mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-04 03:27:12 -05:00 
			
		
		
		
	Fixes relative date Whoosh queries and adds testing to ensure it remains working with multiple timezones
This commit is contained in:
		
							parent
							
								
									dae4550bc3
								
							
						
					
					
						commit
						dc7bef5d48
					
				@ -5,6 +5,7 @@ from contextlib import contextmanager
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from dateutil.parser import isoparse
 | 
					from dateutil.parser import isoparse
 | 
				
			||||||
from django.conf import settings
 | 
					from django.conf import settings
 | 
				
			||||||
 | 
					from django.utils import timezone
 | 
				
			||||||
from documents.models import Comment
 | 
					from documents.models import Comment
 | 
				
			||||||
from documents.models import Document
 | 
					from documents.models import Document
 | 
				
			||||||
from whoosh import classify
 | 
					from whoosh import classify
 | 
				
			||||||
@ -262,7 +263,7 @@ class DelayedFullTextQuery(DelayedQuery):
 | 
				
			|||||||
            ["content", "title", "correspondent", "tag", "type", "comments"],
 | 
					            ["content", "title", "correspondent", "tag", "type", "comments"],
 | 
				
			||||||
            self.searcher.ixreader.schema,
 | 
					            self.searcher.ixreader.schema,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        qp.add_plugin(DateParserPlugin())
 | 
					        qp.add_plugin(DateParserPlugin(basedate=timezone.now()))
 | 
				
			||||||
        q = qp.parse(q_str)
 | 
					        q = qp.parse(q_str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        corrected = self.searcher.correct_query(q, q_str)
 | 
					        corrected = self.searcher.correct_query(q, q_str)
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ import tempfile
 | 
				
			|||||||
import urllib.request
 | 
					import urllib.request
 | 
				
			||||||
import uuid
 | 
					import uuid
 | 
				
			||||||
import zipfile
 | 
					import zipfile
 | 
				
			||||||
 | 
					from datetime import timedelta
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from unittest import mock
 | 
					from unittest import mock
 | 
				
			||||||
from unittest.mock import MagicMock
 | 
					from unittest.mock import MagicMock
 | 
				
			||||||
@ -23,6 +24,7 @@ from django.conf import settings
 | 
				
			|||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
from django.test import override_settings
 | 
					from django.test import override_settings
 | 
				
			||||||
from django.utils import timezone
 | 
					from django.utils import timezone
 | 
				
			||||||
 | 
					from dateutil.relativedelta import relativedelta
 | 
				
			||||||
from documents import bulk_edit
 | 
					from documents import bulk_edit
 | 
				
			||||||
from documents import index
 | 
					from documents import index
 | 
				
			||||||
from documents.models import Correspondent
 | 
					from documents.models import Correspondent
 | 
				
			||||||
@ -505,6 +507,270 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
 | 
				
			|||||||
        response = self.client.get("/api/documents/?query=content&page=3&page_size=10")
 | 
					        response = self.client.get("/api/documents/?query=content&page=3&page_size=10")
 | 
				
			||||||
        self.assertEqual(response.status_code, 404)
 | 
					        self.assertEqual(response.status_code, 404)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @override_settings(
 | 
				
			||||||
 | 
					        TIME_ZONE="UTC",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    def test_search_added_in_last_week(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        GIVEN:
 | 
				
			||||||
 | 
					            - Three documents added right now
 | 
				
			||||||
 | 
					            - The timezone is UTC time
 | 
				
			||||||
 | 
					        WHEN:
 | 
				
			||||||
 | 
					            - Query for documents added in the last 7 days
 | 
				
			||||||
 | 
					        THEN:
 | 
				
			||||||
 | 
					            - The two recent documents are returned
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        d1 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="invoice",
 | 
				
			||||||
 | 
					            content="the thing i bought at a shop and paid with bank account",
 | 
				
			||||||
 | 
					            checksum="A",
 | 
				
			||||||
 | 
					            pk=1,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d2 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 1",
 | 
				
			||||||
 | 
					            content="things i paid for in august",
 | 
				
			||||||
 | 
					            pk=2,
 | 
				
			||||||
 | 
					            checksum="B",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d3 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 3",
 | 
				
			||||||
 | 
					            content="things i paid for in september",
 | 
				
			||||||
 | 
					            pk=3,
 | 
				
			||||||
 | 
					            checksum="C",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        with index.open_index_writer() as writer:
 | 
				
			||||||
 | 
					            index.update_document(writer, d1)
 | 
				
			||||||
 | 
					            index.update_document(writer, d2)
 | 
				
			||||||
 | 
					            index.update_document(writer, d3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?query=added:[-1 week to now]")
 | 
				
			||||||
 | 
					        results = response.data["results"]
 | 
				
			||||||
 | 
					        # Expect 3 documents returned
 | 
				
			||||||
 | 
					        self.assertEqual(len(results), 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for idx, subset in enumerate(
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                {"id": 1, "title": "invoice"},
 | 
				
			||||||
 | 
					                {"id": 2, "title": "bank statement 1"},
 | 
				
			||||||
 | 
					                {"id": 3, "title": "bank statement 3"},
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
 | 
					            result = results[idx]
 | 
				
			||||||
 | 
					            # Assert subset in results
 | 
				
			||||||
 | 
					            self.assertDictEqual(result, {**result, **subset})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @override_settings(
 | 
				
			||||||
 | 
					        TIME_ZONE="America/Chicago",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    def test_search_added_in_last_week_with_timezone_behind(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        GIVEN:
 | 
				
			||||||
 | 
					            - Two documents added right now
 | 
				
			||||||
 | 
					            - One document added over a week ago
 | 
				
			||||||
 | 
					            - The timezone is behind UTC time (-6)
 | 
				
			||||||
 | 
					        WHEN:
 | 
				
			||||||
 | 
					            - Query for documents added in the last 7 days
 | 
				
			||||||
 | 
					        THEN:
 | 
				
			||||||
 | 
					            - The two recent documents are returned
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        d1 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="invoice",
 | 
				
			||||||
 | 
					            content="the thing i bought at a shop and paid with bank account",
 | 
				
			||||||
 | 
					            checksum="A",
 | 
				
			||||||
 | 
					            pk=1,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d2 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 1",
 | 
				
			||||||
 | 
					            content="things i paid for in august",
 | 
				
			||||||
 | 
					            pk=2,
 | 
				
			||||||
 | 
					            checksum="B",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d3 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 3",
 | 
				
			||||||
 | 
					            content="things i paid for in september",
 | 
				
			||||||
 | 
					            pk=3,
 | 
				
			||||||
 | 
					            checksum="C",
 | 
				
			||||||
 | 
					            # 7 days, 1 hour and 1 minute ago
 | 
				
			||||||
 | 
					            added=timezone.now() - timedelta(days=7, hours=1, minutes=1),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        with index.open_index_writer() as writer:
 | 
				
			||||||
 | 
					            index.update_document(writer, d1)
 | 
				
			||||||
 | 
					            index.update_document(writer, d2)
 | 
				
			||||||
 | 
					            index.update_document(writer, d3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?query=added:[-1 week to now]")
 | 
				
			||||||
 | 
					        results = response.data["results"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Expect 2 documents returned
 | 
				
			||||||
 | 
					        self.assertEqual(len(results), 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for idx, subset in enumerate(
 | 
				
			||||||
 | 
					            [{"id": 1, "title": "invoice"}, {"id": 2, "title": "bank statement 1"}],
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
 | 
					            result = results[idx]
 | 
				
			||||||
 | 
					            # Assert subset in results
 | 
				
			||||||
 | 
					            self.assertDictEqual(result, {**result, **subset})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @override_settings(
 | 
				
			||||||
 | 
					        TIME_ZONE="Europe/Sofia",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    def test_search_added_in_last_week_with_timezone_ahead(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        GIVEN:
 | 
				
			||||||
 | 
					            - Two documents added right now
 | 
				
			||||||
 | 
					            - One document added over a week ago
 | 
				
			||||||
 | 
					            - The timezone is behind UTC time (+2)
 | 
				
			||||||
 | 
					        WHEN:
 | 
				
			||||||
 | 
					            - Query for documents added in the last 7 days
 | 
				
			||||||
 | 
					        THEN:
 | 
				
			||||||
 | 
					            - The two recent documents are returned
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        d1 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="invoice",
 | 
				
			||||||
 | 
					            content="the thing i bought at a shop and paid with bank account",
 | 
				
			||||||
 | 
					            checksum="A",
 | 
				
			||||||
 | 
					            pk=1,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d2 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 1",
 | 
				
			||||||
 | 
					            content="things i paid for in august",
 | 
				
			||||||
 | 
					            pk=2,
 | 
				
			||||||
 | 
					            checksum="B",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d3 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 3",
 | 
				
			||||||
 | 
					            content="things i paid for in september",
 | 
				
			||||||
 | 
					            pk=3,
 | 
				
			||||||
 | 
					            checksum="C",
 | 
				
			||||||
 | 
					            # 7 days, 1 hour and 1 minute ago
 | 
				
			||||||
 | 
					            added=timezone.now() - timedelta(days=7, hours=1, minutes=1),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        with index.open_index_writer() as writer:
 | 
				
			||||||
 | 
					            index.update_document(writer, d1)
 | 
				
			||||||
 | 
					            index.update_document(writer, d2)
 | 
				
			||||||
 | 
					            index.update_document(writer, d3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?query=added:[-1 week to now]")
 | 
				
			||||||
 | 
					        results = response.data["results"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Expect 2 documents returned
 | 
				
			||||||
 | 
					        self.assertEqual(len(results), 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for idx, subset in enumerate(
 | 
				
			||||||
 | 
					            [{"id": 1, "title": "invoice"}, {"id": 2, "title": "bank statement 1"}],
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
 | 
					            result = results[idx]
 | 
				
			||||||
 | 
					            # Assert subset in results
 | 
				
			||||||
 | 
					            self.assertDictEqual(result, {**result, **subset})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_search_added_in_last_month(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        GIVEN:
 | 
				
			||||||
 | 
					            - One document added right now
 | 
				
			||||||
 | 
					            - One documents added about a week ago
 | 
				
			||||||
 | 
					            - One document added over 1 month
 | 
				
			||||||
 | 
					        WHEN:
 | 
				
			||||||
 | 
					            - Query for documents added in the last month
 | 
				
			||||||
 | 
					        THEN:
 | 
				
			||||||
 | 
					            - The two recent documents are returned
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        d1 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="invoice",
 | 
				
			||||||
 | 
					            content="the thing i bought at a shop and paid with bank account",
 | 
				
			||||||
 | 
					            checksum="A",
 | 
				
			||||||
 | 
					            pk=1,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d2 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 1",
 | 
				
			||||||
 | 
					            content="things i paid for in august",
 | 
				
			||||||
 | 
					            pk=2,
 | 
				
			||||||
 | 
					            checksum="B",
 | 
				
			||||||
 | 
					            # 1 month, 1 day ago
 | 
				
			||||||
 | 
					            added=timezone.now() - relativedelta(months=1, days=1),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d3 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 3",
 | 
				
			||||||
 | 
					            content="things i paid for in september",
 | 
				
			||||||
 | 
					            pk=3,
 | 
				
			||||||
 | 
					            checksum="C",
 | 
				
			||||||
 | 
					            # 7 days, 1 hour and 1 minute ago
 | 
				
			||||||
 | 
					            added=timezone.now() - timedelta(days=7, hours=1, minutes=1),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with index.open_index_writer() as writer:
 | 
				
			||||||
 | 
					            index.update_document(writer, d1)
 | 
				
			||||||
 | 
					            index.update_document(writer, d2)
 | 
				
			||||||
 | 
					            index.update_document(writer, d3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?query=added:[-1 month to now]")
 | 
				
			||||||
 | 
					        results = response.data["results"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Expect 2 documents returned
 | 
				
			||||||
 | 
					        self.assertEqual(len(results), 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for idx, subset in enumerate(
 | 
				
			||||||
 | 
					            [{"id": 1, "title": "invoice"}, {"id": 3, "title": "bank statement 3"}],
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
 | 
					            result = results[idx]
 | 
				
			||||||
 | 
					            # Assert subset in results
 | 
				
			||||||
 | 
					            self.assertDictEqual(result, {**result, **subset})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @override_settings(
 | 
				
			||||||
 | 
					        TIME_ZONE="America/Denver",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    def test_search_added_in_last_month_timezone_behind(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        GIVEN:
 | 
				
			||||||
 | 
					            - One document added right now
 | 
				
			||||||
 | 
					            - One documents added about a week ago
 | 
				
			||||||
 | 
					            - One document added over 1 month
 | 
				
			||||||
 | 
					            - The timezone is behind UTC time (-6 or -7)
 | 
				
			||||||
 | 
					        WHEN:
 | 
				
			||||||
 | 
					            - Query for documents added in the last month
 | 
				
			||||||
 | 
					        THEN:
 | 
				
			||||||
 | 
					            - The two recent documents are returned
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        d1 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="invoice",
 | 
				
			||||||
 | 
					            content="the thing i bought at a shop and paid with bank account",
 | 
				
			||||||
 | 
					            checksum="A",
 | 
				
			||||||
 | 
					            pk=1,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d2 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 1",
 | 
				
			||||||
 | 
					            content="things i paid for in august",
 | 
				
			||||||
 | 
					            pk=2,
 | 
				
			||||||
 | 
					            checksum="B",
 | 
				
			||||||
 | 
					            # 1 month, 1 day ago
 | 
				
			||||||
 | 
					            added=timezone.now() - relativedelta(months=1, days=1),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        d3 = Document.objects.create(
 | 
				
			||||||
 | 
					            title="bank statement 3",
 | 
				
			||||||
 | 
					            content="things i paid for in september",
 | 
				
			||||||
 | 
					            pk=3,
 | 
				
			||||||
 | 
					            checksum="C",
 | 
				
			||||||
 | 
					            # 7 days, 1 hour and 1 minute ago
 | 
				
			||||||
 | 
					            added=timezone.now() - timedelta(days=7, hours=1, minutes=1),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with index.open_index_writer() as writer:
 | 
				
			||||||
 | 
					            index.update_document(writer, d1)
 | 
				
			||||||
 | 
					            index.update_document(writer, d2)
 | 
				
			||||||
 | 
					            index.update_document(writer, d3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?query=added:[-1 month to now]")
 | 
				
			||||||
 | 
					        results = response.data["results"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Expect 2 documents returned
 | 
				
			||||||
 | 
					        self.assertEqual(len(results), 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for idx, subset in enumerate(
 | 
				
			||||||
 | 
					            [{"id": 1, "title": "invoice"}, {"id": 3, "title": "bank statement 3"}],
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
 | 
					            result = results[idx]
 | 
				
			||||||
 | 
					            # Assert subset in results
 | 
				
			||||||
 | 
					            self.assertDictEqual(result, {**result, **subset})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @mock.patch("documents.index.autocomplete")
 | 
					    @mock.patch("documents.index.autocomplete")
 | 
				
			||||||
    def test_search_autocomplete(self, m):
 | 
					    def test_search_autocomplete(self, m):
 | 
				
			||||||
        m.side_effect = lambda ix, term, limit: [term for _ in range(limit)]
 | 
					        m.side_effect = lambda ix, term, limit: [term for _ in range(limit)]
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user