WIP: add asn prefix

This commit is contained in:
Jakob Englisch 2025-01-05 18:58:29 +01:00
parent aef68f0b41
commit d974bc542e
16 changed files with 179 additions and 12 deletions

View File

@ -12,6 +12,14 @@
</div> </div>
<div class="position-relative" [class.col-md-9]="horizontal"> <div class="position-relative" [class.col-md-9]="horizontal">
<div class="input-group" [class.is-invalid]="error"> <div class="input-group" [class.is-invalid]="error">
@if (prefix) {
<ng-select class="form-control"
[items]="prefix"
bindLabel="name"
bindValue="id"
[(ngModel)]="prefixSelect"
></ng-select>
}
<input #inputField type="number" class="form-control" [step]="step" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [class.is-invalid]="error" [disabled]="disabled"> <input #inputField type="number" class="form-control" [step]="step" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [class.is-invalid]="error" [disabled]="disabled">
@if (showAdd) { @if (showAdd) {
<button class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="disabled">+1</button> <button class="btn btn-outline-secondary" type="button" id="button-addon1" (click)="nextAsn()" [disabled]="disabled">+1</button>

View File

@ -2,11 +2,13 @@ import { Component, forwardRef, Input } from '@angular/core'
import { import {
FormsModule, FormsModule,
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR,
ReactiveFormsModule, ReactiveFormsModule
} from '@angular/forms' } from '@angular/forms'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { DocumentService } from 'src/app/services/rest/document.service' import { DocumentService } from 'src/app/services/rest/document.service'
import { AbstractInputComponent } from '../abstract-input' import { AbstractInputComponent } from '../abstract-input'
import { NgSelectModule } from '@ng-select/ng-select'
import { AsnPrefix } from "../../../../data/asn-prefix";
@Component({ @Component({
providers: [ providers: [
@ -19,12 +21,18 @@ import { AbstractInputComponent } from '../abstract-input'
selector: 'pngx-input-number', selector: 'pngx-input-number',
templateUrl: './number.component.html', templateUrl: './number.component.html',
styleUrls: ['./number.component.scss'], styleUrls: ['./number.component.scss'],
imports: [FormsModule, ReactiveFormsModule, NgxBootstrapIconsModule], imports: [FormsModule, ReactiveFormsModule, NgxBootstrapIconsModule, NgSelectModule],
}) })
export class NumberComponent extends AbstractInputComponent<number> { export class NumberComponent extends AbstractInputComponent<number> {
@Input() @Input()
showAdd: boolean = true showAdd: boolean = true
@Input()
prefix: AsnPrefix[]
@Input()
prefixSelect: number
@Input() @Input()
step: number = 1 step: number = 1

View File

@ -106,7 +106,7 @@
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div> <div>
<pngx-input-text #inputTitle i18n-title title="Title" formControlName="title" [horizontal]="true" (keyup)="titleKeyUp($event)" [error]="error?.title"></pngx-input-text> <pngx-input-text #inputTitle i18n-title title="Title" formControlName="title" [horizontal]="true" (keyup)="titleKeyUp($event)" [error]="error?.title"></pngx-input-text>
<pngx-input-number i18n-title title="Archive serial number" [error]="error?.archive_serial_number" [horizontal]="true" formControlName='archive_serial_number'></pngx-input-number> <pngx-input-number [prefix]="asnPrefix" [prefixSelect]="archive_serial_number_prefix" i18n-title title="Archive serial number" [error]="error?.archive_serial_number" [horizontal]="true" formControlName='archive_serial_number'></pngx-input-number>
<pngx-input-date i18n-title title="Date created" formControlName="created_date" [suggestions]="suggestions?.dates" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)" <pngx-input-date i18n-title title="Date created" formControlName="created_date" [suggestions]="suggestions?.dates" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event)"
[error]="error?.created_date"></pngx-input-date> [error]="error?.created_date"></pngx-input-date>
<pngx-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.Correspondent)" <pngx-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true" [showFilter]="true" [horizontal]="true" (filterDocuments)="filterDocuments($event, DataType.Correspondent)"

View File

@ -67,6 +67,7 @@ import {
PermissionsService, PermissionsService,
PermissionType, PermissionType,
} from 'src/app/services/permissions.service' } from 'src/app/services/permissions.service'
import { AsnPrefixService } from 'src/app/services/rest/asn-prefix.service'
import { CorrespondentService } from 'src/app/services/rest/correspondent.service' import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service' import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
import { DocumentTypeService } from 'src/app/services/rest/document-type.service' import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
@ -102,6 +103,7 @@ import { DocumentHistoryComponent } from '../document-history/document-history.c
import { DocumentNotesComponent } from '../document-notes/document-notes.component' import { DocumentNotesComponent } from '../document-notes/document-notes.component'
import { ComponentWithPermissions } from '../with-permissions/with-permissions.component' import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
import { MetadataCollapseComponent } from './metadata-collapse/metadata-collapse.component' import { MetadataCollapseComponent } from './metadata-collapse/metadata-collapse.component'
import { AsnPrefix } from "../../data/asn-prefix";
enum DocumentDetailNavIDs { enum DocumentDetailNavIDs {
Details = 1, Details = 1,
@ -171,8 +173,7 @@ enum ZoomSetting {
}) })
export class DocumentDetailComponent export class DocumentDetailComponent
extends ComponentWithPermissions extends ComponentWithPermissions
implements OnInit, OnDestroy, DirtyComponent implements OnInit, OnDestroy, DirtyComponent {
{
@ViewChild('inputTitle') @ViewChild('inputTitle')
titleInput: TextComponent titleInput: TextComponent
@ -200,6 +201,7 @@ export class DocumentDetailComponent
tiffURL: string tiffURL: string
tiffError: string tiffError: string
asnPrefix: AsnPrefix[]
correspondents: Correspondent[] correspondents: Correspondent[]
documentTypes: DocumentType[] documentTypes: DocumentType[]
storagePaths: StoragePath[] storagePaths: StoragePath[]
@ -211,6 +213,7 @@ export class DocumentDetailComponent
correspondent: new FormControl(), correspondent: new FormControl(),
document_type: new FormControl(), document_type: new FormControl(),
storage_path: new FormControl(), storage_path: new FormControl(),
archive_serial_number_prefix: new FormControl(),
archive_serial_number: new FormControl(), archive_serial_number: new FormControl(),
tags: new FormControl([]), tags: new FormControl([]),
permissions_form: new FormControl(null), permissions_form: new FormControl(null),
@ -258,6 +261,7 @@ export class DocumentDetailComponent
constructor( constructor(
private documentsService: DocumentService, private documentsService: DocumentService,
private route: ActivatedRoute, private route: ActivatedRoute,
private asnPrefixService: AsnPrefixService,
private correspondentService: CorrespondentService, private correspondentService: CorrespondentService,
private documentTypeService: DocumentTypeService, private documentTypeService: DocumentTypeService,
private router: Router, private router: Router,
@ -347,6 +351,17 @@ export class DocumentDetailComponent
.pipe(first(), takeUntil(this.unsubscribeNotifier)) .pipe(first(), takeUntil(this.unsubscribeNotifier))
.subscribe((result) => (this.correspondents = result.results)) .subscribe((result) => (this.correspondents = result.results))
} }
if (
this.permissionsService.currentUserCan(
PermissionAction.View,
PermissionType.AsnPrefix
)
) {
this.asnPrefixService
.listAll()
.pipe(first(), takeUntil(this.unsubscribeNotifier))
.subscribe((result) => (this.asnPrefix = result.results))
}
if ( if (
this.permissionsService.currentUserCan( this.permissionsService.currentUserCan(
PermissionAction.View, PermissionAction.View,
@ -403,9 +418,8 @@ export class DocumentDetailComponent
this.previewText = res.toString() this.previewText = res.toString()
}, },
error: (err) => { error: (err) => {
this.previewText = $localize`An error occurred loading content: ${ this.previewText = $localize`An error occurred loading content: ${err.message ?? err.toString()
err.message ?? err.toString() }`
}`
}, },
}) })
this.thumbUrl = this.documentsService.getThumbUrl(documentId) this.thumbUrl = this.documentsService.getThumbUrl(documentId)
@ -449,7 +463,7 @@ export class DocumentDetailComponent
this.documentForm.get('permissions_form').value['owner'] this.documentForm.get('permissions_form').value['owner']
openDocument['permissions'] = openDocument['permissions'] =
this.documentForm.get('permissions_form').value[ this.documentForm.get('permissions_form').value[
'set_permissions' 'set_permissions'
] ]
delete openDocument['permissions_form'] delete openDocument['permissions_form']
} }
@ -494,6 +508,7 @@ export class DocumentDetailComponent
correspondent: doc.correspondent, correspondent: doc.correspondent,
document_type: doc.document_type, document_type: doc.document_type,
storage_path: doc.storage_path, storage_path: doc.storage_path,
archive_serial_number_prefix: doc.archive_serial_number_prefix,
archive_serial_number: doc.archive_serial_number, archive_serial_number: doc.archive_serial_number,
tags: [...doc.tags], tags: [...doc.tags],
permissions_form: { permissions_form: {
@ -793,7 +808,7 @@ export class DocumentDetailComponent
save(close: boolean = false) { save(close: boolean = false) {
this.networkActive = true this.networkActive = true
;(document.activeElement as HTMLElement)?.dispatchEvent(new Event('change')) ; (document.activeElement as HTMLElement)?.dispatchEvent(new Event('change'))
this.documentsService this.documentsService
.update(this.document) .update(this.document)
.pipe(first()) .pipe(first())
@ -1046,7 +1061,7 @@ export class DocumentDetailComponent
this.previewZoomScale = ZoomSetting.PageWidth this.previewZoomScale = ZoomSetting.PageWidth
this.previewZoomSetting = this.previewZoomSetting =
Object.values(ZoomSetting)[ Object.values(ZoomSetting)[
Math.min(Object.values(ZoomSetting).length - 1, currentIndex + 1) Math.min(Object.values(ZoomSetting).length - 1, currentIndex + 1)
] ]
} }

View File

@ -0,0 +1,9 @@
import {ObjectWithId} from "./object-with-id";
export interface AsnPrefix extends ObjectWithId {
name?: string
slug?: string
document_count?: number
}

View File

@ -1,4 +1,5 @@
import { Observable } from 'rxjs' import { Observable } from 'rxjs'
import { AsnPrefix } from './asn-prefix'
import { Correspondent } from './correspondent' import { Correspondent } from './correspondent'
import { CustomFieldInstance } from './custom-field-instance' import { CustomFieldInstance } from './custom-field-instance'
import { DocumentNote } from './document-note' import { DocumentNote } from './document-note'
@ -118,6 +119,10 @@ export interface SearchHit {
} }
export interface Document extends ObjectWithPermissions { export interface Document extends ObjectWithPermissions {
archive_serial_number_prefix$?: Observable<AsnPrefix>
archive_serial_number_prefix?: number
correspondent$?: Observable<Correspondent> correspondent$?: Observable<Correspondent>
correspondent?: number correspondent?: number

View File

@ -12,6 +12,7 @@ export enum PermissionAction {
export enum PermissionType { export enum PermissionType {
Document = '%s_document', Document = '%s_document',
Tag = '%s_tag', Tag = '%s_tag',
AsnPrefix = '%s_asnprefix',
Correspondent = '%s_correspondent', Correspondent = '%s_correspondent',
DocumentType = '%s_documenttype', DocumentType = '%s_documenttype',
StoragePath = '%s_storagepath', StoragePath = '%s_storagepath',

View File

@ -0,0 +1,13 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { AsnPrefix } from 'src/app/data/asn-prefix'
import { AbstractNameFilterService } from './abstract-name-filter-service'
@Injectable({
providedIn: 'root',
})
export class AsnPrefixService extends AbstractNameFilterService<AsnPrefix> {
constructor(http: HttpClient) {
super(http, 'asn_prefix')
}
}

View File

@ -2,6 +2,7 @@ from django.conf import settings
from django.contrib import admin from django.contrib import admin
from guardian.admin import GuardedModelAdmin from guardian.admin import GuardedModelAdmin
from documents.models import ArchiveSerialNumberPrefix
from documents.models import Correspondent from documents.models import Correspondent
from documents.models import CustomField from documents.models import CustomField
from documents.models import CustomFieldInstance from documents.models import CustomFieldInstance
@ -38,6 +39,10 @@ class DocumentTypeAdmin(GuardedModelAdmin):
list_filter = ("matching_algorithm",) list_filter = ("matching_algorithm",)
list_editable = ("match", "matching_algorithm") list_editable = ("match", "matching_algorithm")
class ArchiveSerialNumberPrefixAdmin(GuardedModelAdmin):
list_display = ("name", "owner")
list_filter = ("name",)
#list_editable = ("name",)
class DocumentAdmin(GuardedModelAdmin): class DocumentAdmin(GuardedModelAdmin):
search_fields = ("correspondent__name", "title", "content", "tags__name") search_fields = ("correspondent__name", "title", "content", "tags__name")
@ -60,6 +65,7 @@ class DocumentAdmin(GuardedModelAdmin):
list_filter = ( list_filter = (
("mime_type"), ("mime_type"),
("archive_serial_number_prefix", admin.EmptyFieldListFilter),
("archive_serial_number", admin.EmptyFieldListFilter), ("archive_serial_number", admin.EmptyFieldListFilter),
("archive_filename", admin.EmptyFieldListFilter), ("archive_filename", admin.EmptyFieldListFilter),
) )
@ -195,6 +201,7 @@ class CustomFieldInstancesAdmin(GuardedModelAdmin):
admin.site.register(Correspondent, CorrespondentAdmin) admin.site.register(Correspondent, CorrespondentAdmin)
admin.site.register(Tag, TagAdmin) admin.site.register(Tag, TagAdmin)
admin.site.register(DocumentType, DocumentTypeAdmin) admin.site.register(DocumentType, DocumentTypeAdmin)
admin.site.register(ArchiveSerialNumberPrefix, ArchiveSerialNumberPrefixAdmin)
admin.site.register(Document, DocumentAdmin) admin.site.register(Document, DocumentAdmin)
admin.site.register(SavedView, SavedViewAdmin) admin.site.register(SavedView, SavedViewAdmin)
admin.site.register(StoragePath, StoragePathAdmin) admin.site.register(StoragePath, StoragePathAdmin)

View File

@ -28,6 +28,7 @@ from rest_framework import serializers
from rest_framework.filters import OrderingFilter from rest_framework.filters import OrderingFilter
from rest_framework_guardian.filters import ObjectPermissionsFilter from rest_framework_guardian.filters import ObjectPermissionsFilter
from documents.models import ArchiveSerialNumberPrefix
from documents.models import Correspondent from documents.models import Correspondent
from documents.models import CustomField from documents.models import CustomField
from documents.models import CustomFieldInstance from documents.models import CustomFieldInstance
@ -65,6 +66,14 @@ class TagFilterSet(FilterSet):
} }
class ArchiveSerialNumberPrefixFilterSet(FilterSet):
class Meta:
model = ArchiveSerialNumberPrefix
fields = {
"id": ID_KWARGS,
"name": CHAR_KWARGS,
}
class DocumentTypeFilterSet(FilterSet): class DocumentTypeFilterSet(FilterSet):
class Meta: class Meta:
model = DocumentType model = DocumentType

View File

@ -245,6 +245,7 @@ class DelayedQuery:
"title": "title", "title": "title",
"correspondent__name": "correspondent", "correspondent__name": "correspondent",
"document_type__name": "type", "document_type__name": "type",
"archive_serial_number_prefix": "asn_prefix",
"archive_serial_number": "asn", "archive_serial_number": "asn",
"num_notes": "num_notes", "num_notes": "num_notes",
"owner": "owner", "owner": "owner",

View File

@ -0,0 +1,32 @@
# Generated by Django 5.1.4 on 2025-01-05 16:53
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('documents', '1060_alter_customfieldinstance_value_select'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='ArchiveSerialNumberPrefix',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=6, verbose_name='name')),
('owner', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='owner')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='document',
name='archive_serial_number_prefix',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='documents', to='documents.archiveserialnumberprefix', verbose_name='archive serial number prefix'),
),
]

View File

@ -95,6 +95,13 @@ class MatchingModel(ModelWithOwner):
return self.name return self.name
class ArchiveSerialNumberPrefix(ModelWithOwner):
name = models.CharField(_("name"), max_length=6)
def __str__(self):
return self.name
class Correspondent(MatchingModel): class Correspondent(MatchingModel):
class Meta(MatchingModel.Meta): class Meta(MatchingModel.Meta):
verbose_name = _("correspondent") verbose_name = _("correspondent")
@ -272,6 +279,15 @@ class Document(SoftDeleteModel, ModelWithOwner):
help_text=_("The original name of the file when it was uploaded"), help_text=_("The original name of the file when it was uploaded"),
) )
archive_serial_number_prefix = models.ForeignKey(
ArchiveSerialNumberPrefix,
blank=True,
null=True,
related_name="documents",
on_delete=models.SET_NULL,
verbose_name=_("archive serial number prefix"),
)
ARCHIVE_SERIAL_NUMBER_MIN: Final[int] = 0 ARCHIVE_SERIAL_NUMBER_MIN: Final[int] = 0
ARCHIVE_SERIAL_NUMBER_MAX: Final[int] = 0xFF_FF_FF_FF ARCHIVE_SERIAL_NUMBER_MAX: Final[int] = 0xFF_FF_FF_FF

View File

@ -34,6 +34,7 @@ if settings.AUDIT_LOG_ENABLED:
from documents import bulk_edit from documents import bulk_edit
from documents.data_models import DocumentSource from documents.data_models import DocumentSource
from documents.models import ArchiveSerialNumberPrefix
from documents.models import Correspondent from documents.models import Correspondent
from documents.models import CustomField from documents.models import CustomField
from documents.models import CustomFieldInstance from documents.models import CustomFieldInstance
@ -342,6 +343,22 @@ class OwnedObjectListSerializer(serializers.ListSerializer):
return super().to_representation(documents) return super().to_representation(documents)
class ArchiveSerialNumberPrefixSerializer(MatchingModelSerializer, OwnedObjectSerializer):
class Meta:
model = ArchiveSerialNumberPrefix
fields = (
"id",
"slug",
"name",
"document_count",
"owner",
"permissions",
"user_can_change",
"set_permissions",
)
class CorrespondentSerializer(MatchingModelSerializer, OwnedObjectSerializer): class CorrespondentSerializer(MatchingModelSerializer, OwnedObjectSerializer):
last_correspondence = serializers.DateTimeField(read_only=True, required=False) last_correspondence = serializers.DateTimeField(read_only=True, required=False)
@ -362,7 +379,6 @@ class CorrespondentSerializer(MatchingModelSerializer, OwnedObjectSerializer):
"set_permissions", "set_permissions",
) )
class DocumentTypeSerializer(MatchingModelSerializer, OwnedObjectSerializer): class DocumentTypeSerializer(MatchingModelSerializer, OwnedObjectSerializer):
class Meta: class Meta:
model = DocumentType model = DocumentType
@ -474,6 +490,9 @@ class TagSerializer(MatchingModelSerializer, OwnedObjectSerializer):
raise serializers.ValidationError(_("Invalid color.")) raise serializers.ValidationError(_("Invalid color."))
return color return color
class ArchiveSerialNumberPrefixField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
return ArchiveSerialNumberPrefix.objects.all()
class CorrespondentField(serializers.PrimaryKeyRelatedField): class CorrespondentField(serializers.PrimaryKeyRelatedField):
def get_queryset(self): def get_queryset(self):
@ -778,6 +797,7 @@ class DocumentSerializer(
NestedUpdateMixin, NestedUpdateMixin,
DynamicFieldsModelSerializer, DynamicFieldsModelSerializer,
): ):
archive_serial_number_prefix = ArchiveSerialNumberPrefixField(allow_null=True)
correspondent = CorrespondentField(allow_null=True) correspondent = CorrespondentField(allow_null=True)
tags = TagsField(many=True) tags = TagsField(many=True)
document_type = DocumentTypeField(allow_null=True) document_type = DocumentTypeField(allow_null=True)
@ -832,6 +852,7 @@ class DocumentSerializer(
and len(str(attrs["archive_serial_number"])) > 0 and len(str(attrs["archive_serial_number"])) > 0
and Document.deleted_objects.filter( and Document.deleted_objects.filter(
archive_serial_number=attrs["archive_serial_number"], archive_serial_number=attrs["archive_serial_number"],
#archive_serial_number_prefix__prefix=attrs["archive_serial_number_prefix"], # TODO: asn type empty is allowed
).exists() ).exists()
): ):
raise serializers.ValidationError( raise serializers.ValidationError(
@ -934,6 +955,7 @@ class DocumentSerializer(
"modified", "modified",
"added", "added",
"deleted_at", "deleted_at",
"archive_serial_number_prefix",
"archive_serial_number", "archive_serial_number",
"original_file_name", "original_file_name",
"archived_file_name", "archived_file_name",

View File

@ -93,6 +93,7 @@ from documents.conditionals import thumbnail_last_modified
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
from documents.filters import ArchiveSerialNumberPrefixFilterSet
from documents.filters import CorrespondentFilterSet from documents.filters import CorrespondentFilterSet
from documents.filters import CustomFieldFilterSet from documents.filters import CustomFieldFilterSet
from documents.filters import DocumentFilterSet from documents.filters import DocumentFilterSet
@ -107,6 +108,7 @@ from documents.matching import match_correspondents
from documents.matching import match_document_types from documents.matching import match_document_types
from documents.matching import match_storage_paths from documents.matching import match_storage_paths
from documents.matching import match_tags from documents.matching import match_tags
from documents.models import ArchiveSerialNumberPrefix
from documents.models import Correspondent from documents.models import Correspondent
from documents.models import CustomField from documents.models import CustomField
from documents.models import Document from documents.models import Document
@ -130,6 +132,7 @@ from documents.permissions import get_objects_for_user_owner_aware
from documents.permissions import has_perms_owner_aware from documents.permissions import has_perms_owner_aware
from documents.permissions import set_permissions_for_object from documents.permissions import set_permissions_for_object
from documents.serialisers import AcknowledgeTasksViewSerializer from documents.serialisers import AcknowledgeTasksViewSerializer
from documents.serialisers import ArchiveSerialNumberPrefixSerializer
from documents.serialisers import BulkDownloadSerializer from documents.serialisers import BulkDownloadSerializer
from documents.serialisers import BulkEditObjectsSerializer from documents.serialisers import BulkEditObjectsSerializer
from documents.serialisers import BulkEditSerializer from documents.serialisers import BulkEditSerializer
@ -258,6 +261,22 @@ class PermissionsAwareDocumentCountMixin(PassUserMixin):
) )
class ArchiveSerialNumberPrefixViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin):
model = ArchiveSerialNumberPrefix
queryset = ArchiveSerialNumberPrefix.objects.select_related("owner").order_by(Lower("name"))
serializer_class = ArchiveSerialNumberPrefixSerializer
pagination_class = StandardPagination
permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
filter_backends = (
DjangoFilterBackend,
OrderingFilter,
ObjectOwnedOrGrantedPermissionsFilter,
)
filterset_class = ArchiveSerialNumberPrefixFilterSet
ordering_fields = ("name")
class CorrespondentViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin): class CorrespondentViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin):
model = Correspondent model = Correspondent

View File

@ -17,6 +17,7 @@ from django.views.static import serve
from rest_framework.authtoken import views from rest_framework.authtoken import views
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from documents.views import ArchiveSerialNumberPrefixViewSet
from documents.views import BulkDownloadView from documents.views import BulkDownloadView
from documents.views import BulkEditObjectsView from documents.views import BulkEditObjectsView
from documents.views import BulkEditView from documents.views import BulkEditView
@ -59,6 +60,7 @@ from paperless_mail.views import MailRuleViewSet
from paperless_mail.views import OauthCallbackView from paperless_mail.views import OauthCallbackView
api_router = DefaultRouter() api_router = DefaultRouter()
api_router.register(r"asn_prefix", ArchiveSerialNumberPrefixViewSet)
api_router.register(r"correspondents", CorrespondentViewSet) api_router.register(r"correspondents", CorrespondentViewSet)
api_router.register(r"document_types", DocumentTypeViewSet) api_router.register(r"document_types", DocumentTypeViewSet)
api_router.register(r"documents", UnifiedSearchViewSet) api_router.register(r"documents", UnifiedSearchViewSet)