diff --git a/src-ui/src/app/components/common/input/number/number.component.spec.ts b/src-ui/src/app/components/common/input/number/number.component.spec.ts index bf1b40d38..dfe1673db 100644 --- a/src-ui/src/app/components/common/input/number/number.component.spec.ts +++ b/src-ui/src/app/components/common/input/number/number.component.spec.ts @@ -30,39 +30,9 @@ describe('NumberComponent', () => { input = component.inputField.nativeElement }) - // TODO: why doesnt this work? - // it('should support use of input field', () => { - // expect(component.value).toBeUndefined() - // input.stepUp() - // console.log(input.value); - - // input.dispatchEvent(new Event('change')) - // fixture.detectChanges() - // expect(component.value).toEqual('3') - // }) - it('should support +1 ASN', () => { - const listAllSpy = jest.spyOn(documentService, 'listFiltered') - listAllSpy - .mockReturnValueOnce( - of({ - count: 1, - all: [1], - results: [ - { - id: 1, - archive_serial_number: 1000, - }, - ], - }) - ) - .mockReturnValueOnce( - of({ - count: 0, - all: [], - results: [], - }) - ) + const nextAsnSpy = jest.spyOn(documentService, 'getNextAsn') + nextAsnSpy.mockReturnValueOnce(of(1001)).mockReturnValueOnce(of(1)) expect(component.value).toBeUndefined() component.nextAsn() expect(component.value).toEqual(1001) diff --git a/src-ui/src/app/components/common/input/number/number.component.ts b/src-ui/src/app/components/common/input/number/number.component.ts index 25271044f..682cd8036 100644 --- a/src-ui/src/app/components/common/input/number/number.component.ts +++ b/src-ui/src/app/components/common/input/number/number.component.ts @@ -1,6 +1,5 @@ import { Component, forwardRef, Input } from '@angular/core' import { NG_VALUE_ACCESSOR } from '@angular/forms' -import { FILTER_ASN_ISNULL } from 'src/app/data/filter-rule-type' import { DocumentService } from 'src/app/services/rest/document.service' import { AbstractInputComponent } from '../abstract-input' @@ -28,17 +27,9 @@ export class NumberComponent extends AbstractInputComponent { if (this.value) { return } - this.documentService - .listFiltered(1, 1, 'archive_serial_number', true, [ - { rule_type: FILTER_ASN_ISNULL, value: 'false' }, - ]) - .subscribe((results) => { - if (results.count > 0) { - this.value = results.results[0].archive_serial_number + 1 - } else { - this.value = 1 - } - this.onChange(this.value) - }) + this.documentService.getNextAsn().subscribe((nextAsn) => { + this.value = nextAsn + this.onChange(this.value) + }) } } diff --git a/src-ui/src/app/services/rest/document.service.spec.ts b/src-ui/src/app/services/rest/document.service.spec.ts index be1128de4..8576a2399 100644 --- a/src-ui/src/app/services/rest/document.service.spec.ts +++ b/src-ui/src/app/services/rest/document.service.spec.ts @@ -229,6 +229,14 @@ describe(`DocumentService`, () => { `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/preview/#search="${searchQuery}"` ) }) + + it('should support get next asn', () => { + subscription = service.getNextAsn().subscribe((asn) => asn) + const req = httpTestingController.expectOne( + `${environment.apiBaseUrl}${endpoint}/next_asn/` + ) + expect(req.request.method).toEqual('GET') + }) }) beforeEach(() => { diff --git a/src-ui/src/app/services/rest/document.service.ts b/src-ui/src/app/services/rest/document.service.ts index 08050ac85..9c1d4b61d 100644 --- a/src-ui/src/app/services/rest/document.service.ts +++ b/src-ui/src/app/services/rest/document.service.ts @@ -143,6 +143,10 @@ export class DocumentService extends AbstractPaperlessService return url } + getNextAsn(): Observable { + return this.http.get(this.getResourceUrl(null, 'next_asn')) + } + update(o: PaperlessDocument): Observable { // we want to only set created_date o.created = undefined diff --git a/src/documents/tests/test_api.py b/src/documents/tests/test_api.py index a47c78dc5..783d2d444 100644 --- a/src/documents/tests/test_api.py +++ b/src/documents/tests/test_api.py @@ -2689,6 +2689,50 @@ class TestDocumentApi(DirectoriesMixin, DocumentConsumeDelayMixin, APITestCase): ) self.assertEqual(resp.status_code, status.HTTP_200_OK) + def test_next_asn(self): + """ + GIVEN: + - Existing documents with ASNs, highest owned by user2 + WHEN: + - API request is made by user1 to get next ASN + THEN: + - ASN +1 from user2's doc is returned for user1 + """ + user1 = User.objects.create_user(username="test1") + user1.user_permissions.add(*Permission.objects.all()) + user1.save() + + user2 = User.objects.create_user(username="test2") + user2.save() + + doc1 = Document.objects.create( + title="test", + mime_type="application/pdf", + content="this is a document 1", + checksum="1", + archive_serial_number=998, + ) + doc1.owner = user1 + doc1.save() + + doc2 = Document.objects.create( + title="test2", + mime_type="application/pdf", + content="this is a document 2 with higher ASN", + checksum="2", + archive_serial_number=999, + ) + doc2.owner = user2 + doc2.save() + + self.client.force_authenticate(user1) + + resp = self.client.get( + "/api/documents/next_asn/", + ) + self.assertEqual(resp.status_code, status.HTTP_200_OK) + self.assertEqual(resp.content, b"1000") + class TestDocumentApiV2(DirectoriesMixin, APITestCase): def setUp(self): diff --git a/src/documents/views.py b/src/documents/views.py index 9440741e7..2445a09b0 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -661,6 +661,19 @@ class UnifiedSearchViewSet(DocumentViewSet): else: return super().list(request) + @action(detail=False, methods=["GET"], name="Get Next ASN") + def next_asn(self, request, *args, **kwargs): + return Response( + ( + Document.objects.filter(archive_serial_number__gte=0) + .order_by("archive_serial_number") + .last() + .archive_serial_number + or 0 + ) + + 1, + ) + class LogViewSet(ViewSet): permission_classes = (IsAuthenticated, PaperlessAdminPermissions)