mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-01-12 21:44:21 -06:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f23433bd57 | ||
|
|
c968505f64 | ||
|
|
fbb5864757 |
@@ -13,6 +13,7 @@ from pikepdf import Page
|
|||||||
from pikepdf import PasswordError
|
from pikepdf import PasswordError
|
||||||
from pikepdf import Pdf
|
from pikepdf import Pdf
|
||||||
|
|
||||||
|
from documents.consumer import ConsumerPreflightPlugin
|
||||||
from documents.converters import convert_from_tiff_to_pdf
|
from documents.converters import convert_from_tiff_to_pdf
|
||||||
from documents.data_models import ConsumableDocument
|
from documents.data_models import ConsumableDocument
|
||||||
from documents.data_models import DocumentMetadataOverrides
|
from documents.data_models import DocumentMetadataOverrides
|
||||||
@@ -193,6 +194,15 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
|||||||
):
|
):
|
||||||
logger.info(f"Found ASN in barcode: {located_asn}")
|
logger.info(f"Found ASN in barcode: {located_asn}")
|
||||||
self.metadata.asn = located_asn
|
self.metadata.asn = located_asn
|
||||||
|
# (Re-)run the preflight ASN check
|
||||||
|
preflight_plugin = ConsumerPreflightPlugin(
|
||||||
|
input_doc=self.input_doc,
|
||||||
|
metadata=self.metadata,
|
||||||
|
status_mgr=self.status_mgr,
|
||||||
|
base_tmp_dir=self.base_tmp_dir,
|
||||||
|
task_id=self.task_id,
|
||||||
|
)
|
||||||
|
preflight_plugin.pre_check_asn_value()
|
||||||
|
|
||||||
def cleanup(self) -> None:
|
def cleanup(self) -> None:
|
||||||
self.temp_dir.cleanup()
|
self.temp_dir.cleanup()
|
||||||
|
|||||||
@@ -580,10 +580,6 @@ class TagSerializer(MatchingModelSerializer, OwnedObjectSerializer):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
def get_children(self, obj):
|
def get_children(self, obj):
|
||||||
children_map = self.context.get("children_map")
|
|
||||||
if children_map is not None:
|
|
||||||
children = children_map.get(obj.pk, [])
|
|
||||||
else:
|
|
||||||
filter_q = self.context.get("document_count_filter")
|
filter_q = self.context.get("document_count_filter")
|
||||||
request = self.context.get("request")
|
request = self.context.get("request")
|
||||||
if filter_q is None:
|
if filter_q is None:
|
||||||
@@ -591,7 +587,7 @@ class TagSerializer(MatchingModelSerializer, OwnedObjectSerializer):
|
|||||||
filter_q = get_document_count_filter_for_user(user)
|
filter_q = get_document_count_filter_for_user(user)
|
||||||
self.context["document_count_filter"] = filter_q
|
self.context["document_count_filter"] = filter_q
|
||||||
|
|
||||||
children = (
|
children_queryset = (
|
||||||
obj.get_children_queryset()
|
obj.get_children_queryset()
|
||||||
.select_related("owner")
|
.select_related("owner")
|
||||||
.annotate(document_count=Count("documents", filter=filter_q))
|
.annotate(document_count=Count("documents", filter=filter_q))
|
||||||
@@ -599,15 +595,15 @@ class TagSerializer(MatchingModelSerializer, OwnedObjectSerializer):
|
|||||||
|
|
||||||
view = self.context.get("view")
|
view = self.context.get("view")
|
||||||
ordering = (
|
ordering = (
|
||||||
OrderingFilter().get_ordering(request, children, view)
|
OrderingFilter().get_ordering(request, children_queryset, view)
|
||||||
if request and view
|
if request and view
|
||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
ordering = ordering or (Lower("name"),)
|
ordering = ordering or (Lower("name"),)
|
||||||
children = children.order_by(*ordering)
|
children_queryset = children_queryset.order_by(*ordering)
|
||||||
|
|
||||||
serializer = TagSerializer(
|
serializer = TagSerializer(
|
||||||
children,
|
children_queryset,
|
||||||
many=True,
|
many=True,
|
||||||
user=self.user,
|
user=self.user,
|
||||||
full_perms=self.full_perms,
|
full_perms=self.full_perms,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from django.test import override_settings
|
|||||||
|
|
||||||
from documents import tasks
|
from documents import tasks
|
||||||
from documents.barcodes import BarcodePlugin
|
from documents.barcodes import BarcodePlugin
|
||||||
|
from documents.consumer import ConsumerError
|
||||||
from documents.data_models import ConsumableDocument
|
from documents.data_models import ConsumableDocument
|
||||||
from documents.data_models import DocumentMetadataOverrides
|
from documents.data_models import DocumentMetadataOverrides
|
||||||
from documents.data_models import DocumentSource
|
from documents.data_models import DocumentSource
|
||||||
@@ -93,6 +94,41 @@ class TestBarcode(
|
|||||||
|
|
||||||
self.assertDictEqual(separator_page_numbers, {1: False})
|
self.assertDictEqual(separator_page_numbers, {1: False})
|
||||||
|
|
||||||
|
@override_settings(CONSUMER_ENABLE_ASN_BARCODE=True)
|
||||||
|
def test_asn_barcode_duplicate_in_trash_fails(self):
|
||||||
|
"""
|
||||||
|
GIVEN:
|
||||||
|
- A document with ASN barcode 123 is in the trash
|
||||||
|
WHEN:
|
||||||
|
- A file with the same barcode ASN is consumed
|
||||||
|
THEN:
|
||||||
|
- The ASN check is re-run and consumption fails
|
||||||
|
"""
|
||||||
|
test_file = self.BARCODE_SAMPLE_DIR / "barcode-39-asn-123.pdf"
|
||||||
|
|
||||||
|
first_doc = Document.objects.create(
|
||||||
|
title="First ASN 123",
|
||||||
|
content="",
|
||||||
|
checksum="asn123first",
|
||||||
|
mime_type="application/pdf",
|
||||||
|
archive_serial_number=123,
|
||||||
|
)
|
||||||
|
|
||||||
|
first_doc.delete()
|
||||||
|
|
||||||
|
dupe_asn = settings.SCRATCH_DIR / "barcode-39-asn-123-second.pdf"
|
||||||
|
shutil.copy(test_file, dupe_asn)
|
||||||
|
|
||||||
|
with mock.patch("documents.tasks.ProgressManager", DummyProgressManager):
|
||||||
|
with self.assertRaisesRegex(ConsumerError, r"ASN 123.*trash"):
|
||||||
|
tasks.consume_file(
|
||||||
|
ConsumableDocument(
|
||||||
|
source=DocumentSource.ConsumeFolder,
|
||||||
|
original_file=dupe_asn,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
CONSUMER_BARCODE_TIFF_SUPPORT=True,
|
CONSUMER_BARCODE_TIFF_SUPPORT=True,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -448,43 +448,8 @@ class TagViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin):
|
|||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
context = super().get_serializer_context()
|
context = super().get_serializer_context()
|
||||||
context["document_count_filter"] = self.get_document_count_filter()
|
context["document_count_filter"] = self.get_document_count_filter()
|
||||||
if hasattr(self, "_children_map"):
|
|
||||||
context["children_map"] = self._children_map
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Build a children map once to avoid per-parent queries in the serializer.
|
|
||||||
"""
|
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
|
||||||
ordering = OrderingFilter().get_ordering(request, queryset, self) or (
|
|
||||||
Lower("name"),
|
|
||||||
)
|
|
||||||
queryset = queryset.order_by(*ordering)
|
|
||||||
|
|
||||||
all_tags = list(queryset)
|
|
||||||
descendant_pks = {pk for tag in all_tags for pk in tag.get_descendants_pks()}
|
|
||||||
|
|
||||||
if descendant_pks:
|
|
||||||
filter_q = self.get_document_count_filter()
|
|
||||||
children_source = (
|
|
||||||
Tag.objects.filter(pk__in=descendant_pks | {t.pk for t in all_tags})
|
|
||||||
.select_related("owner")
|
|
||||||
.annotate(document_count=Count("documents", filter=filter_q))
|
|
||||||
.order_by(*ordering)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
children_source = all_tags
|
|
||||||
|
|
||||||
children_map = {}
|
|
||||||
for tag in children_source:
|
|
||||||
children_map.setdefault(tag.tn_parent_id, []).append(tag)
|
|
||||||
self._children_map = children_map
|
|
||||||
|
|
||||||
page = self.paginate_queryset(queryset)
|
|
||||||
serializer = self.get_serializer(page, many=True)
|
|
||||||
return self.get_paginated_response(serializer.data)
|
|
||||||
|
|
||||||
def perform_update(self, serializer):
|
def perform_update(self, serializer):
|
||||||
old_parent = self.get_object().get_parent()
|
old_parent = self.get_object().get_parent()
|
||||||
tag = serializer.save()
|
tag = serializer.save()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: paperless-ngx\n"
|
"Project-Id-Version: paperless-ngx\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-01-12 21:04+0000\n"
|
"POT-Creation-Date: 2026-01-08 21:50+0000\n"
|
||||||
"PO-Revision-Date: 2022-02-17 04:17\n"
|
"PO-Revision-Date: 2022-02-17 04:17\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: English\n"
|
"Language-Team: English\n"
|
||||||
@@ -1219,35 +1219,35 @@ msgstr ""
|
|||||||
msgid "workflow runs"
|
msgid "workflow runs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/serialisers.py:646
|
#: documents/serialisers.py:642
|
||||||
msgid "Invalid color."
|
msgid "Invalid color."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/serialisers.py:1850
|
#: documents/serialisers.py:1846
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "File type %(type)s not supported"
|
msgid "File type %(type)s not supported"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/serialisers.py:1894
|
#: documents/serialisers.py:1890
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Custom field id must be an integer: %(id)s"
|
msgid "Custom field id must be an integer: %(id)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/serialisers.py:1901
|
#: documents/serialisers.py:1897
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Custom field with id %(id)s does not exist"
|
msgid "Custom field with id %(id)s does not exist"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/serialisers.py:1918 documents/serialisers.py:1928
|
#: documents/serialisers.py:1914 documents/serialisers.py:1924
|
||||||
msgid ""
|
msgid ""
|
||||||
"Custom fields must be a list of integers or an object mapping ids to values."
|
"Custom fields must be a list of integers or an object mapping ids to values."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/serialisers.py:1923
|
#: documents/serialisers.py:1919
|
||||||
msgid "Some custom fields don't exist or were specified twice."
|
msgid "Some custom fields don't exist or were specified twice."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/serialisers.py:2038
|
#: documents/serialisers.py:2034
|
||||||
msgid "Invalid variable detected."
|
msgid "Invalid variable detected."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user