mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-23 10:39:25 -05:00
Merge db00617c6aba905c9b14b2bb2dcf4028bba42856 into 5a278381e38c4583d6285d07bb922e5068a987d0
This commit is contained in:
commit
e7c51e3544
@ -105,9 +105,9 @@ describe('ConfigComponent', () => {
|
||||
|
||||
it('should support JSON validation for e.g. user_args', () => {
|
||||
component.configForm.patchValue({ user_args: '{ foo bar }' })
|
||||
expect(component.errors).toEqual({ user_args: 'Invalid JSON' })
|
||||
expect(component.errors['user_args']).toEqual('Invalid JSON')
|
||||
component.configForm.patchValue({ user_args: '{ "foo": "bar" }' })
|
||||
expect(component.errors).toEqual({ user_args: null })
|
||||
expect(component.errors['user_args']).toBeNull()
|
||||
})
|
||||
|
||||
it('should upload file, show error if necessary', () => {
|
||||
|
@ -49,6 +49,7 @@ export enum ConfigOptionType {
|
||||
export const ConfigCategory = {
|
||||
General: $localize`General Settings`,
|
||||
OCR: $localize`OCR Settings`,
|
||||
Barcode: $localize`Barcode Settings`,
|
||||
}
|
||||
|
||||
export interface ConfigOption {
|
||||
@ -180,6 +181,83 @@ export const PaperlessConfigOptions: ConfigOption[] = [
|
||||
config_key: 'PAPERLESS_APP_TITLE',
|
||||
category: ConfigCategory.General,
|
||||
},
|
||||
{
|
||||
key: 'barcodes_enabled',
|
||||
title: $localize`Enable Barcodes`,
|
||||
type: ConfigOptionType.Boolean,
|
||||
config_key: 'PAPERLESS_CONSUMER_ENABLE_BARCODES',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_enable_tiff_support',
|
||||
title: $localize`Enable TIFF Support`,
|
||||
type: ConfigOptionType.Boolean,
|
||||
config_key: 'PAPERLESS_CONSUMER_BARCODE_TIFF_SUPPORT',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_string',
|
||||
title: $localize`Barcode String`,
|
||||
type: ConfigOptionType.String,
|
||||
config_key: 'PAPERLESS_CONSUMER_BARCODE_STRING',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_retain_split_pages',
|
||||
title: $localize`Retain Split Pages`,
|
||||
type: ConfigOptionType.Boolean,
|
||||
config_key: 'PAPERLESS_CONSUMER_BARCODE_RETAIN_SPLIT_PAGES',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_enable_asn',
|
||||
title: $localize`Enable ASN`,
|
||||
type: ConfigOptionType.Boolean,
|
||||
config_key: 'PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_asn_prefix',
|
||||
title: $localize`ASN Prefix`,
|
||||
type: ConfigOptionType.String,
|
||||
config_key: 'PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_upscale',
|
||||
title: $localize`Upscale`,
|
||||
type: ConfigOptionType.Number,
|
||||
config_key: 'PAPERLESS_CONSUMER_BARCODE_UPSCALE',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_dpi',
|
||||
title: $localize`DPI`,
|
||||
type: ConfigOptionType.Number,
|
||||
config_key: 'PAPERLESS_CONSUMER_BARCODE_DPI',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_max_pages',
|
||||
title: $localize`Max Pages`,
|
||||
type: ConfigOptionType.Number,
|
||||
config_key: 'PAPERLESS_CONSUMER_BARCODE_MAX_PAGES',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_enable_tag',
|
||||
title: $localize`Enable Tag Detection`,
|
||||
type: ConfigOptionType.Boolean,
|
||||
config_key: 'PAPERLESS_CONSUMER_ENABLE_TAG_BARCODE',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_tag_mapping',
|
||||
title: $localize`Tag Mapping`,
|
||||
type: ConfigOptionType.JSON,
|
||||
config_key: 'PAPERLESS_CONSUMER_TAG_BARCODE_MAPPING',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
]
|
||||
|
||||
export interface PaperlessConfig extends ObjectWithId {
|
||||
@ -198,4 +276,15 @@ export interface PaperlessConfig extends ObjectWithId {
|
||||
user_args: object
|
||||
app_logo: string
|
||||
app_title: string
|
||||
barcodes_enabled: boolean
|
||||
barcode_enable_tiff_support: boolean
|
||||
barcode_string: string
|
||||
barcode_retain_split_pages: boolean
|
||||
barcode_enable_asn: boolean
|
||||
barcode_asn_prefix: string
|
||||
barcode_upscale: number
|
||||
barcode_dpi: number
|
||||
barcode_max_pages: number
|
||||
barcode_enable_tag: boolean
|
||||
barcode_tag_mapping: object
|
||||
}
|
||||
|
@ -32,28 +32,39 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase):
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
self.assertEqual(
|
||||
json.dumps(response.data[0]),
|
||||
json.dumps(
|
||||
{
|
||||
"id": 1,
|
||||
"user_args": None,
|
||||
"output_type": None,
|
||||
"pages": None,
|
||||
"language": None,
|
||||
"mode": None,
|
||||
"skip_archive_file": None,
|
||||
"image_dpi": None,
|
||||
"unpaper_clean": None,
|
||||
"deskew": None,
|
||||
"rotate_pages": None,
|
||||
"rotate_pages_threshold": None,
|
||||
"max_image_pixels": None,
|
||||
"color_conversion_strategy": None,
|
||||
"app_title": None,
|
||||
"app_logo": None,
|
||||
},
|
||||
),
|
||||
self.maxDiff = None
|
||||
|
||||
self.assertDictEqual(
|
||||
response.data[0],
|
||||
{
|
||||
"id": 1,
|
||||
"output_type": None,
|
||||
"pages": None,
|
||||
"language": None,
|
||||
"mode": None,
|
||||
"skip_archive_file": None,
|
||||
"image_dpi": None,
|
||||
"unpaper_clean": None,
|
||||
"deskew": None,
|
||||
"rotate_pages": None,
|
||||
"rotate_pages_threshold": None,
|
||||
"max_image_pixels": None,
|
||||
"color_conversion_strategy": None,
|
||||
"user_args": None,
|
||||
"app_title": None,
|
||||
"app_logo": None,
|
||||
"barcodes_enabled": None,
|
||||
"barcode_enable_tiff_support": None,
|
||||
"barcode_string": None,
|
||||
"barcode_retain_split_pages": None,
|
||||
"barcode_enable_asn": None,
|
||||
"barcode_asn_prefix": None,
|
||||
"barcode_upscale": None,
|
||||
"barcode_dpi": None,
|
||||
"barcode_max_pages": None,
|
||||
"barcode_enable_tag": None,
|
||||
"barcode_tag_mapping": None,
|
||||
},
|
||||
)
|
||||
|
||||
def test_api_get_ui_settings_with_config(self):
|
||||
|
@ -55,6 +55,17 @@ class OcrConfig(OutputTypeConfig):
|
||||
max_image_pixel: float | None = dataclasses.field(init=False)
|
||||
color_conversion_strategy: str = dataclasses.field(init=False)
|
||||
user_args: dict[str, str] | None = dataclasses.field(init=False)
|
||||
barcodes_enabled: bool = dataclasses.field(init=False)
|
||||
barcode_enable_tiff_support: bool = dataclasses.field(init=False)
|
||||
barcode_string: str = dataclasses.field(init=False)
|
||||
barcode_retain_split_pages: bool = dataclasses.field(init=False)
|
||||
barcode_enable_asn: bool = dataclasses.field(init=False)
|
||||
barcode_asn_prefix: str = dataclasses.field(init=False)
|
||||
barcode_upscale: float = dataclasses.field(init=False)
|
||||
barcode_dpi: int = dataclasses.field(init=False)
|
||||
barcode_max_pages: int = dataclasses.field(init=False)
|
||||
barcode_enable_tag: bool = dataclasses.field(init=False)
|
||||
barcode_tag_mapping: dict[str, str] = dataclasses.field(init=False)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
super().__post_init__()
|
||||
@ -96,9 +107,42 @@ class OcrConfig(OutputTypeConfig):
|
||||
user_args = json.loads(settings.OCR_USER_ARGS)
|
||||
except json.JSONDecodeError:
|
||||
user_args = {}
|
||||
|
||||
self.user_args = user_args
|
||||
|
||||
self.barcodes_enabled = (
|
||||
app_config.barcodes_enabled or settings.CONSUMER_ENABLE_BARCODES
|
||||
)
|
||||
self.barcode_enable_tiff_support = (
|
||||
app_config.barcode_enable_tiff_support
|
||||
or settings.CONSUMER_BARCODE_TIFF_SUPPORT
|
||||
)
|
||||
self.barcode_string = (
|
||||
app_config.barcode_string or settings.CONSUMER_BARCODE_STRING
|
||||
)
|
||||
self.barcode_retain_split_pages = (
|
||||
app_config.barcode_retain_split_pages
|
||||
or settings.CONSUMER_BARCODE_RETAIN_SPLIT_PAGES
|
||||
)
|
||||
self.barcode_enable_asn = (
|
||||
app_config.barcode_enable_asn or settings.CONSUMER_ENABLE_ASN_BARCODE
|
||||
)
|
||||
self.barcode_asn_prefix = (
|
||||
app_config.barcode_asn_prefix or settings.CONSUMER_ASN_BARCODE_PREFIX
|
||||
)
|
||||
self.barcode_upscale = (
|
||||
app_config.barcode_upscale or settings.CONSUMER_BARCODE_UPSCALE
|
||||
)
|
||||
self.barcode_dpi = app_config.barcode_dpi or settings.CONSUMER_BARCODE_DPI
|
||||
self.barcode_max_pages = (
|
||||
app_config.barcode_max_pages or settings.CONSUMER_BARCODE_MAX_PAGES
|
||||
)
|
||||
self.barcode_enable_tag = (
|
||||
app_config.barcode_enable_tag or settings.CONSUMER_ENABLE_TAG_BARCODE
|
||||
)
|
||||
self.barcode_tag_mapping = (
|
||||
app_config.barcode_tag_mapping or settings.CONSUMER_TAG_BARCODE_MAPPING
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class GeneralConfig(BaseConfig):
|
||||
|
@ -0,0 +1,100 @@
|
||||
# Generated by Django 5.1.7 on 2025-04-02 19:21
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("paperless", "0003_alter_applicationconfiguration_max_image_pixels"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_asn_prefix",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
max_length=32,
|
||||
null=True,
|
||||
verbose_name="Sets the ASN barcode prefix",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_dpi",
|
||||
field=models.PositiveIntegerField(
|
||||
null=True,
|
||||
validators=[django.core.validators.MinValueValidator(1)],
|
||||
verbose_name="Sets the barcode DPI",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_enable_asn",
|
||||
field=models.BooleanField(null=True, verbose_name="Enables ASN barcode"),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_enable_tag",
|
||||
field=models.BooleanField(null=True, verbose_name="Enables tag barcode"),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_enable_tiff_support",
|
||||
field=models.BooleanField(
|
||||
null=True,
|
||||
verbose_name="Enables barcode TIFF support",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_max_pages",
|
||||
field=models.PositiveIntegerField(
|
||||
null=True,
|
||||
validators=[django.core.validators.MinValueValidator(1)],
|
||||
verbose_name="Sets the maximum pages for barcode",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_retain_split_pages",
|
||||
field=models.BooleanField(null=True, verbose_name="Retains split pages"),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_string",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
max_length=32,
|
||||
null=True,
|
||||
verbose_name="Sets the barcode string",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_tag_mapping",
|
||||
field=models.JSONField(
|
||||
null=True,
|
||||
verbose_name="Sets the tag barcode mapping",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcode_upscale",
|
||||
field=models.FloatField(
|
||||
null=True,
|
||||
validators=[django.core.validators.MinValueValidator(1.0)],
|
||||
verbose_name="Sets the barcode upscale factor",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="barcodes_enabled",
|
||||
field=models.BooleanField(
|
||||
null=True,
|
||||
verbose_name="Enables barcode scanning",
|
||||
),
|
||||
),
|
||||
]
|
@ -167,6 +167,10 @@ class ApplicationConfiguration(AbstractSingletonModel):
|
||||
null=True,
|
||||
)
|
||||
|
||||
"""
|
||||
Settings for the Paperless application
|
||||
"""
|
||||
|
||||
app_title = models.CharField(
|
||||
verbose_name=_("Application title"),
|
||||
null=True,
|
||||
@ -184,6 +188,83 @@ class ApplicationConfiguration(AbstractSingletonModel):
|
||||
upload_to="logo/",
|
||||
)
|
||||
|
||||
"""
|
||||
Settings for the barcode scanner
|
||||
"""
|
||||
|
||||
# PAPERLESS_CONSUMER_ENABLE_BARCODES
|
||||
barcodes_enabled = models.BooleanField(
|
||||
verbose_name=_("Enables barcode scanning"),
|
||||
null=True,
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_BARCODE_TIFF_SUPPORT
|
||||
barcode_enable_tiff_support = models.BooleanField(
|
||||
verbose_name=_("Enables barcode TIFF support"),
|
||||
null=True,
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_BARCODE_STRING
|
||||
barcode_string = models.CharField(
|
||||
verbose_name=_("Sets the barcode string"),
|
||||
null=True,
|
||||
blank=True,
|
||||
max_length=32,
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_BARCODE_RETAIN_SPLIT_PAGES
|
||||
barcode_retain_split_pages = models.BooleanField(
|
||||
verbose_name=_("Retains split pages"),
|
||||
null=True,
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE
|
||||
barcode_enable_asn = models.BooleanField(
|
||||
verbose_name=_("Enables ASN barcode"),
|
||||
null=True,
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX
|
||||
barcode_asn_prefix = models.CharField(
|
||||
verbose_name=_("Sets the ASN barcode prefix"),
|
||||
null=True,
|
||||
blank=True,
|
||||
max_length=32,
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_BARCODE_UPSCALE
|
||||
barcode_upscale = models.FloatField(
|
||||
verbose_name=_("Sets the barcode upscale factor"),
|
||||
null=True,
|
||||
validators=[MinValueValidator(1.0)],
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_BARCODE_DPI
|
||||
barcode_dpi = models.PositiveIntegerField(
|
||||
verbose_name=_("Sets the barcode DPI"),
|
||||
null=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_BARCODE_MAX_PAGES
|
||||
barcode_max_pages = models.PositiveIntegerField(
|
||||
verbose_name=_("Sets the maximum pages for barcode"),
|
||||
null=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_ENABLE_TAG_BARCODE
|
||||
barcode_enable_tag = models.BooleanField(
|
||||
verbose_name=_("Enables tag barcode"),
|
||||
null=True,
|
||||
)
|
||||
|
||||
# PAPERLESS_CONSUMER_TAG_BARCODE_MAPPING
|
||||
barcode_tag_mapping = models.JSONField(
|
||||
verbose_name=_("Sets the tag barcode mapping"),
|
||||
null=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("paperless application settings")
|
||||
|
||||
|
@ -185,11 +185,14 @@ class ProfileSerializer(serializers.ModelSerializer):
|
||||
|
||||
class ApplicationConfigurationSerializer(serializers.ModelSerializer):
|
||||
user_args = serializers.JSONField(binary=True, allow_null=True)
|
||||
barcode_tag_mapping = serializers.JSONField(binary=True, allow_null=True)
|
||||
|
||||
def run_validation(self, data):
|
||||
# Empty strings treated as None to avoid unexpected behavior
|
||||
if "user_args" in data and data["user_args"] == "":
|
||||
data["user_args"] = None
|
||||
if "barcode_tag_mapping" in data and data["barcode_tag_mapping"] == "":
|
||||
data["barcode_tag_mapping"] = None
|
||||
if "language" in data and data["language"] == "":
|
||||
data["language"] = None
|
||||
return super().run_validation(data)
|
||||
|
Loading…
x
Reference in New Issue
Block a user