mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-07 08:37:13 +00:00
Feature: store barcode contents, list and search them (#14276)
* Feature: store barcode contents, list and search them New setting PAPERLESS_CONSUMER_STORE_BARCODE_VALUES (off by default) stores all barcodes found during consumption with the document: page, type and content. They are listed on the metadata tab with a copy button, returned by the documents API and searchable with barcodes: in the advanced search. Versions keep their own barcodes, reprocessing reads them again. Refs #9898 * Tests: cover the remaining barcode branches Covers unchanged and failing barcode reads on reprocessing, unsupported files and DocumentBarcode.__str__, and uses toHaveLength in the barcode list spec as suggested by SonarCloud. * Address review: keep barcodes when they can't be read, format choices - Reprocessing and new versions keep the stored barcodes when the file can't be scanned or the scan fails, and replace them atomically. - Format is a TextChoices of the zxing-cpp formats, with a test. - Shared scan code, latest_version helper, TypedDict, serializer reuse. - Barcodes in the split manifest, export/import tests, pytest-style tests. * Barcode tests: TIFF reprocess, format check both ways, fixtures - Reprocessing a TIFF with TIFF support off keeps the stored barcodes. - The format test also fails when zxing-cpp drops a format. - Fixtures in place of the sample dir mixin, plugin-level disabled test. - Format labels aren't translated, OpenAPI enum named BarcodeFormatEnum. * Review: module-level zxing reader, shorter barcode docs - read_barcodes_zxing is a module-level function used by scan_pdf. - Drop the trivial __str__ test, mark it no cover. - Shorten the barcode docs and remove the duplicate in configuration.md. * Fix header * Use utility class * Return barcodes from the metadata endpoint only Drop the barcodes field and its prefetches from the document serializer, as agreed in the review. Also remove the now empty component stylesheet. --------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
1 parent
312684aef3
commit
62cc31fbdb
37 files changed
+1196
-80
No files matched your search
@@ -20,6 +20,7 @@ from filelock import FileLock
|
||||
|
||||
from documents import sanity_checker
|
||||
from documents.barcodes import BarcodePlugin
|
||||
from documents.barcodes import read_barcode_values
|
||||
from documents.bulk_download import ArchiveOnlyStrategy
|
||||
from documents.bulk_download import OriginalsOnlyStrategy
|
||||
from documents.caching import clear_document_caches
|
||||
@@ -36,6 +37,7 @@ from documents.data_models import ConsumeFileDuplicateResult
|
||||
from documents.data_models import ConsumeFileStoppedResult
|
||||
from documents.data_models import ConsumeFileSuccessResult
|
||||
from documents.data_models import DocumentMetadataOverrides
|
||||
from documents.data_models import StoredBarcode
|
||||
from documents.double_sided import CollatePlugin
|
||||
from documents.file_handling import create_source_path_directory
|
||||
from documents.file_handling import generate_unique_filename
|
||||
@@ -43,6 +45,7 @@ from documents.matching import prefilter_documents_by_workflowtrigger
|
||||
from documents.models import Correspondent
|
||||
from documents.models import CustomFieldInstance
|
||||
from documents.models import Document
|
||||
from documents.models import DocumentBarcode
|
||||
from documents.models import DocumentType
|
||||
from documents.models import PaperlessTask
|
||||
from documents.models import ShareLink
|
||||
@@ -67,6 +70,7 @@ from documents.utils import identity
|
||||
from documents.versioning import annotate_effective_content
|
||||
from documents.workflows.utils import get_workflows_for_trigger
|
||||
from paperless.config import AIConfig
|
||||
from paperless.config import BarcodeConfig
|
||||
from paperless.config import RemoteOCRConfig
|
||||
from paperless.logging import consume_task_id
|
||||
from paperless.parsers import ParserContext
|
||||
@@ -341,6 +345,29 @@ def bulk_update_documents(document_ids) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _read_barcodes_for_reprocess(document: Document) -> list[StoredBarcode] | None:
|
||||
"""
|
||||
Reads the barcodes of the original again, e.g. for documents consumed
|
||||
before storing them was enabled. Returns None if they should be left as
|
||||
they are: storing is off, the file can't be scanned with the current
|
||||
settings, or the scan failed.
|
||||
"""
|
||||
barcode_settings = BarcodeConfig()
|
||||
if not barcode_settings.barcode_store_values:
|
||||
return None
|
||||
try:
|
||||
with TemporaryDirectory(dir=settings.SCRATCH_DIR) as tmpdir:
|
||||
return read_barcode_values(
|
||||
document.source_path,
|
||||
document.mime_type,
|
||||
barcode_settings,
|
||||
Path(tmpdir),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not read barcodes of document {document}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
@shared_task
|
||||
def update_document_content_maybe_archive_file(
|
||||
document_id,
|
||||
@@ -387,6 +414,8 @@ def update_document_content_maybe_archive_file(
|
||||
produce_archive=produce_archive,
|
||||
)
|
||||
|
||||
barcodes = _read_barcodes_for_reprocess(document)
|
||||
|
||||
thumbnail = parser.get_thumbnail(document.source_path, mime_type)
|
||||
|
||||
with transaction.atomic():
|
||||
@@ -443,6 +472,17 @@ def update_document_content_maybe_archive_file(
|
||||
action=LogEntry.Action.UPDATE,
|
||||
)
|
||||
|
||||
if barcodes is not None:
|
||||
document.barcodes.all().delete()
|
||||
DocumentBarcode.objects.bulk_create(
|
||||
DocumentBarcode(document=document, **barcode)
|
||||
for barcode in barcodes
|
||||
)
|
||||
# metadata_etag includes modified
|
||||
Document.objects.filter(pk=document.pk).update(
|
||||
modified=timezone.now(),
|
||||
)
|
||||
|
||||
with FileLock(settings.MEDIA_LOCK):
|
||||
if parser.get_archive_path():
|
||||
create_source_path_directory(document.archive_path)
|
||||
|
||||
Reference in new issue
Block a user