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:
jurassicparkicecreamandshamoon authored and GitHub committed 2026-10-05 16:25:19 +00:00
1 parent 312684aef3
commit 62cc31fbdb
37 files changed
+1196 -80

No files matched your search

+6
View File
@@ -129,6 +129,7 @@ class BarcodeConfig(BaseConfig):
barcode_enable_tag: bool = dataclasses.field(init=False)
barcode_tag_mapping: dict[str, str] = dataclasses.field(init=False)
barcode_tag_split: bool = dataclasses.field(init=False)
barcode_store_values: bool = dataclasses.field(init=False)
def __post_init__(self) -> None:
app_config = self._get_config_instance()
@@ -179,6 +180,11 @@ class BarcodeConfig(BaseConfig):
if app_config.barcode_tag_split is not None
else settings.CONSUMER_TAG_BARCODE_SPLIT
)
self.barcode_store_values = (
app_config.barcode_store_values
if app_config.barcode_store_values is not None
else settings.CONSUMER_STORE_BARCODE_VALUES
)
@dataclasses.dataclass
@@ -0,0 +1,21 @@
# Generated by Django 5.2.16 on 2026-09-26 14:37
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("paperless", "0017_applicationconfiguration_llm_embedding_api_key"),
]
operations = [
migrations.AddField(
model_name="applicationconfiguration",
name="barcode_store_values",
field=models.BooleanField(
null=True,
verbose_name="Stores the values of detected barcodes",
),
),
]
+6
View File
@@ -303,6 +303,12 @@ class ApplicationConfiguration(AbstractSingletonModel):
null=True,
)
# PAPERLESS_CONSUMER_STORE_BARCODE_VALUES
barcode_store_values = models.BooleanField(
verbose_name=_("Stores the values of detected barcodes"),
null=True,
)
"""
Settings for the remote OCR parser
"""
+5
View File
@@ -229,6 +229,7 @@ SPECTACULAR_SETTINGS = {
},
"ENUM_NAME_OVERRIDES": {
"MatchingAlgorithm": "documents.models.MatchingModel.MATCHING_ALGORITHMS",
"BarcodeFormatEnum": "documents.models.DocumentBarcode.Format",
},
"SCHEMA_PATH_PREFIX_INSERT": FORCE_SCRIPT_NAME or "",
}
@@ -906,6 +907,10 @@ CONSUMER_TAG_BARCODE_SPLIT: Final[bool] = get_bool_from_env(
"PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT",
)
CONSUMER_STORE_BARCODE_VALUES: Final[bool] = get_bool_from_env(
"PAPERLESS_CONSUMER_STORE_BARCODE_VALUES",
)
CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED: Final[bool] = get_bool_from_env(
"PAPERLESS_CONSUMER_ENABLE_COLLATE_DOUBLE_SIDED",
)