mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 03:16:10 -06:00 
			
		
		
		
	Merge branch 'feature-bulk-edit' into feature-bulk-editor
This commit is contained in:
		@@ -5,6 +5,7 @@
 | 
				
			|||||||
      [disabled]="disabled"
 | 
					      [disabled]="disabled"
 | 
				
			||||||
      [style.color]="textColor"
 | 
					      [style.color]="textColor"
 | 
				
			||||||
      [style.background]="backgroundColor"
 | 
					      [style.background]="backgroundColor"
 | 
				
			||||||
 | 
					      [clearable]="allowNull"
 | 
				
			||||||
      (change)="onChange(value)"
 | 
					      (change)="onChange(value)"
 | 
				
			||||||
      (blur)="onTouched()">
 | 
					      (blur)="onTouched()">
 | 
				
			||||||
      <ng-option *ngFor="let i of items" [value]="i.id">{{i.name}}</ng-option>
 | 
					      <ng-option *ngFor="let i of items" [value]="i.id">{{i.name}}</ng-option>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,9 +67,9 @@
 | 
				
			|||||||
                                formControlName='archive_serial_number'>
 | 
					                                formControlName='archive_serial_number'>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <app-input-date-time titleDate="Date created" formControlName="created"></app-input-date-time>
 | 
					                        <app-input-date-time titleDate="Date created" formControlName="created"></app-input-date-time>
 | 
				
			||||||
                        <app-input-select [items]="correspondents" title="Correspondent" formControlName="correspondent"
 | 
					                        <app-input-select [items]="correspondents" title="Correspondent" formControlName="correspondent" [allowNull]="true"
 | 
				
			||||||
                            (createNew)="createCorrespondent()"></app-input-select>
 | 
					                            (createNew)="createCorrespondent()"></app-input-select>
 | 
				
			||||||
                        <app-input-select [items]="documentTypes" title="Document type" formControlName="document_type"
 | 
					                        <app-input-select [items]="documentTypes" title="Document type" formControlName="document_type" [allowNull]="true"
 | 
				
			||||||
                            (createNew)="createDocumentType()"></app-input-select>
 | 
					                            (createNew)="createDocumentType()"></app-input-select>
 | 
				
			||||||
                        <app-input-tags formControlName="tags" title="Tags"></app-input-tags>
 | 
					                        <app-input-tags formControlName="tags" title="Tags"></app-input-tags>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ import { Component, OnInit, ViewChild } from '@angular/core';
 | 
				
			|||||||
import { ActivatedRoute, Router } from '@angular/router';
 | 
					import { ActivatedRoute, Router } from '@angular/router';
 | 
				
			||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
 | 
					import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
 | 
				
			||||||
import { Observable } from 'rxjs';
 | 
					import { Observable } from 'rxjs';
 | 
				
			||||||
import { map } from 'rxjs/operators';
 | 
					import { tap } from 'rxjs/operators';
 | 
				
			||||||
import { PaperlessDocument } from 'src/app/data/paperless-document';
 | 
					import { PaperlessDocument } from 'src/app/data/paperless-document';
 | 
				
			||||||
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view';
 | 
					import { PaperlessSavedView } from 'src/app/data/paperless-saved-view';
 | 
				
			||||||
import { DocumentListViewService } from 'src/app/services/document-list-view.service';
 | 
					import { DocumentListViewService } from 'src/app/services/document-list-view.service';
 | 
				
			||||||
@@ -16,10 +16,8 @@ import { FilterEditorComponent } from './filter-editor/filter-editor.component';
 | 
				
			|||||||
import { ConfirmDialogComponent } from '../common/confirm-dialog/confirm-dialog.component';
 | 
					import { ConfirmDialogComponent } from '../common/confirm-dialog/confirm-dialog.component';
 | 
				
			||||||
import { SelectDialogComponent } from '../common/select-dialog/select-dialog.component';
 | 
					import { SelectDialogComponent } from '../common/select-dialog/select-dialog.component';
 | 
				
			||||||
import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-view-config-dialog.component';
 | 
					import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-view-config-dialog.component';
 | 
				
			||||||
import { PaperlessTag } from 'src/app/data/paperless-tag';
 | 
					 | 
				
			||||||
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent';
 | 
					 | 
				
			||||||
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type';
 | 
					 | 
				
			||||||
import { ChangedItems } from './bulk-editor/bulk-editor.component';
 | 
					import { ChangedItems } from './bulk-editor/bulk-editor.component';
 | 
				
			||||||
 | 
					import { OpenDocumentsService } from 'src/app/services/open-documents.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-document-list',
 | 
					  selector: 'app-document-list',
 | 
				
			||||||
@@ -38,7 +36,8 @@ export class DocumentListComponent implements OnInit {
 | 
				
			|||||||
    private correspondentService: CorrespondentService,
 | 
					    private correspondentService: CorrespondentService,
 | 
				
			||||||
    private documentTypeService: DocumentTypeService,
 | 
					    private documentTypeService: DocumentTypeService,
 | 
				
			||||||
    private tagService: TagService,
 | 
					    private tagService: TagService,
 | 
				
			||||||
    private documentService: DocumentService) { }
 | 
					    private documentService: DocumentService,
 | 
				
			||||||
 | 
					    private openDocumentService: OpenDocumentsService) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @ViewChild("filterEditor")
 | 
					  @ViewChild("filterEditor")
 | 
				
			||||||
  private filterEditor: FilterEditorComponent
 | 
					  private filterEditor: FilterEditorComponent
 | 
				
			||||||
@@ -147,12 +146,12 @@ export class DocumentListComponent implements OnInit {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private executeBulkOperation(method: string, args): Observable<any> {
 | 
					  private executeBulkOperation(method: string, args): Observable<any> {
 | 
				
			||||||
    return this.documentService.bulkEdit(Array.from(this.list.selected), method, args).pipe(
 | 
					    return this.documentService.bulkEdit(Array.from(this.list.selected), method, args).pipe(
 | 
				
			||||||
      map(r => {
 | 
					      tap(() => {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.list.reload()
 | 
					        this.list.reload()
 | 
				
			||||||
 | 
					        this.list.selected.forEach(id => {
 | 
				
			||||||
 | 
					          this.openDocumentService.refreshDocument(id)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
        this.list.selectNone()
 | 
					        this.list.selectNone()
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return r
 | 
					 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
import { Injectable } from '@angular/core';
 | 
					import { Injectable } from '@angular/core';
 | 
				
			||||||
import { PaperlessDocument } from '../data/paperless-document';
 | 
					import { PaperlessDocument } from '../data/paperless-document';
 | 
				
			||||||
import { OPEN_DOCUMENT_SERVICE } from '../data/storage-keys';
 | 
					import { OPEN_DOCUMENT_SERVICE } from '../data/storage-keys';
 | 
				
			||||||
 | 
					import { DocumentService } from './rest/document.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable({
 | 
					@Injectable({
 | 
				
			||||||
  providedIn: 'root'
 | 
					  providedIn: 'root'
 | 
				
			||||||
@@ -9,7 +10,7 @@ export class OpenDocumentsService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private MAX_OPEN_DOCUMENTS = 5
 | 
					  private MAX_OPEN_DOCUMENTS = 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor() { 
 | 
					  constructor(private documentService: DocumentService) { 
 | 
				
			||||||
    if (sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS)) {
 | 
					    if (sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS)) {
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        this.openDocuments = JSON.parse(sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS))
 | 
					        this.openDocuments = JSON.parse(sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS))
 | 
				
			||||||
@@ -22,6 +23,15 @@ export class OpenDocumentsService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private openDocuments: PaperlessDocument[] = []
 | 
					  private openDocuments: PaperlessDocument[] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  refreshDocument(id: number) {
 | 
				
			||||||
 | 
					    let index = this.openDocuments.findIndex(doc => doc.id == id)
 | 
				
			||||||
 | 
					    if (index > -1) {
 | 
				
			||||||
 | 
					      this.documentService.get(id).subscribe(doc => {
 | 
				
			||||||
 | 
					        this.openDocuments[index] = doc
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getOpenDocuments(): PaperlessDocument[] {
 | 
					  getOpenDocuments(): PaperlessDocument[] {
 | 
				
			||||||
    return this.openDocuments
 | 
					    return this.openDocuments
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,6 +51,6 @@ def parser_check(app_configs, **kwargs):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if len(parsers) == 0:
 | 
					    if len(parsers) == 0:
 | 
				
			||||||
        return [Error("No parsers found. This is a bug. The consumer won't be "
 | 
					        return [Error("No parsers found. This is a bug. The consumer won't be "
 | 
				
			||||||
                      "able to onsume any documents without parsers.")]
 | 
					                      "able to consume any documents without parsers.")]
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        return []
 | 
					        return []
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
from django.core.management import BaseCommand
 | 
					from django.core.management import BaseCommand
 | 
				
			||||||
 | 
					from django.db import transaction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from documents.mixins import Renderable
 | 
					from documents.mixins import Renderable
 | 
				
			||||||
from documents.tasks import index_reindex, index_optimize
 | 
					from documents.tasks import index_reindex, index_optimize
 | 
				
			||||||
@@ -18,8 +19,8 @@ class Command(Renderable, BaseCommand):
 | 
				
			|||||||
    def handle(self, *args, **options):
 | 
					    def handle(self, *args, **options):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.verbosity = options["verbosity"]
 | 
					        self.verbosity = options["verbosity"]
 | 
				
			||||||
 | 
					        with transaction.atomic():
 | 
				
			||||||
        if options['command'] == 'reindex':
 | 
					            if options['command'] == 'reindex':
 | 
				
			||||||
            index_reindex()
 | 
					                index_reindex()
 | 
				
			||||||
        elif options['command'] == 'optimize':
 | 
					            elif options['command'] == 'optimize':
 | 
				
			||||||
            index_optimize()
 | 
					                index_optimize()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,6 +64,58 @@ class TestDocumentApi(DirectoriesMixin, APITestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(len(Document.objects.all()), 0)
 | 
					        self.assertEqual(len(Document.objects.all()), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_document_fields(self):
 | 
				
			||||||
 | 
					        c = Correspondent.objects.create(name="c", pk=41)
 | 
				
			||||||
 | 
					        dt = DocumentType.objects.create(name="dt", pk=63)
 | 
				
			||||||
 | 
					        tag = Tag.objects.create(name="t", pk=85)
 | 
				
			||||||
 | 
					        doc = Document.objects.create(title="WOW", content="the content", correspondent=c, document_type=dt, checksum="123", mime_type="application/pdf")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/", format='json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        results_full = response.data['results']
 | 
				
			||||||
 | 
					        self.assertTrue("content" in results_full[0])
 | 
				
			||||||
 | 
					        self.assertTrue("id" in results_full[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?fields=id", format='json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        results = response.data['results']
 | 
				
			||||||
 | 
					        self.assertFalse("content" in results[0])
 | 
				
			||||||
 | 
					        self.assertTrue("id" in results[0])
 | 
				
			||||||
 | 
					        self.assertEqual(len(results[0]), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?fields=content", format='json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        results = response.data['results']
 | 
				
			||||||
 | 
					        self.assertTrue("content" in results[0])
 | 
				
			||||||
 | 
					        self.assertFalse("id" in results[0])
 | 
				
			||||||
 | 
					        self.assertEqual(len(results[0]), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?fields=id,content", format='json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        results = response.data['results']
 | 
				
			||||||
 | 
					        self.assertTrue("content" in results[0])
 | 
				
			||||||
 | 
					        self.assertTrue("id" in results[0])
 | 
				
			||||||
 | 
					        self.assertEqual(len(results[0]), 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?fields=id,conteasdnt", format='json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        results = response.data['results']
 | 
				
			||||||
 | 
					        self.assertFalse("content" in results[0])
 | 
				
			||||||
 | 
					        self.assertTrue("id" in results[0])
 | 
				
			||||||
 | 
					        self.assertEqual(len(results[0]), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?fields=", format='json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        results = response.data['results']
 | 
				
			||||||
 | 
					        self.assertEqual(results_full, results)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = self.client.get("/api/documents/?fields=dgfhs", format='json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        results = response.data['results']
 | 
				
			||||||
 | 
					        self.assertEqual(len(results[0]), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_document_actions(self):
 | 
					    def test_document_actions(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        _, filename = tempfile.mkstemp(dir=self.dirs.originals_dir)
 | 
					        _, filename = tempfile.mkstemp(dir=self.dirs.originals_dir)
 | 
				
			||||||
@@ -683,7 +735,6 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
 | 
				
			|||||||
        args, kwargs = self.async_task.call_args
 | 
					        args, kwargs = self.async_task.call_args
 | 
				
			||||||
        self.assertCountEqual(kwargs['document_ids'], [self.doc1.id, self.doc3.id])
 | 
					        self.assertCountEqual(kwargs['document_ids'], [self.doc1.id, self.doc3.id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_remove_tag(self):
 | 
					    def test_remove_tag(self):
 | 
				
			||||||
        self.assertEqual(Document.objects.filter(tags__id=self.t1.id).count(), 2)
 | 
					        self.assertEqual(Document.objects.filter(tags__id=self.t1.id).count(), 2)
 | 
				
			||||||
        bulk_edit.remove_tag([self.doc1.id, self.doc3.id, self.doc4.id], self.t1.id)
 | 
					        bulk_edit.remove_tag([self.doc1.id, self.doc3.id, self.doc4.id], self.t1.id)
 | 
				
			||||||
@@ -698,15 +749,103 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
 | 
				
			|||||||
        self.assertEqual(Document.objects.count(), 3)
 | 
					        self.assertEqual(Document.objects.count(), 3)
 | 
				
			||||||
        self.assertCountEqual([doc.id for doc in Document.objects.all()], [self.doc3.id, self.doc4.id, self.doc5.id])
 | 
					        self.assertCountEqual([doc.id for doc in Document.objects.all()], [self.doc3.id, self.doc4.id, self.doc5.id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_api(self):
 | 
					    @mock.patch("documents.serialisers.bulk_edit.set_correspondent")
 | 
				
			||||||
        self.assertEqual(Document.objects.count(), 5)
 | 
					    def test_api_set_correspondent(self, m):
 | 
				
			||||||
 | 
					        m.return_value = "OK"
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc1.id],
 | 
				
			||||||
 | 
					            "method": "set_correspondent",
 | 
				
			||||||
 | 
					            "parameters": {"correspondent": self.c1.id}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        m.assert_called_once()
 | 
				
			||||||
 | 
					        args, kwargs = m.call_args
 | 
				
			||||||
 | 
					        self.assertEqual(args[0], [self.doc1.id])
 | 
				
			||||||
 | 
					        self.assertEqual(kwargs['correspondent'], self.c1.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch("documents.serialisers.bulk_edit.set_correspondent")
 | 
				
			||||||
 | 
					    def test_api_unset_correspondent(self, m):
 | 
				
			||||||
 | 
					        m.return_value = "OK"
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc1.id],
 | 
				
			||||||
 | 
					            "method": "set_correspondent",
 | 
				
			||||||
 | 
					            "parameters": {"correspondent": None}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        m.assert_called_once()
 | 
				
			||||||
 | 
					        args, kwargs = m.call_args
 | 
				
			||||||
 | 
					        self.assertEqual(args[0], [self.doc1.id])
 | 
				
			||||||
 | 
					        self.assertIsNone(kwargs['correspondent'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch("documents.serialisers.bulk_edit.set_document_type")
 | 
				
			||||||
 | 
					    def test_api_set_type(self, m):
 | 
				
			||||||
 | 
					        m.return_value = "OK"
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc1.id],
 | 
				
			||||||
 | 
					            "method": "set_document_type",
 | 
				
			||||||
 | 
					            "parameters": {"document_type": self.dt1.id}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        m.assert_called_once()
 | 
				
			||||||
 | 
					        args, kwargs = m.call_args
 | 
				
			||||||
 | 
					        self.assertEqual(args[0], [self.doc1.id])
 | 
				
			||||||
 | 
					        self.assertEqual(kwargs['document_type'], self.dt1.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch("documents.serialisers.bulk_edit.set_document_type")
 | 
				
			||||||
 | 
					    def test_api_unset_type(self, m):
 | 
				
			||||||
 | 
					        m.return_value = "OK"
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc1.id],
 | 
				
			||||||
 | 
					            "method": "set_document_type",
 | 
				
			||||||
 | 
					            "parameters": {"document_type": None}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        m.assert_called_once()
 | 
				
			||||||
 | 
					        args, kwargs = m.call_args
 | 
				
			||||||
 | 
					        self.assertEqual(args[0], [self.doc1.id])
 | 
				
			||||||
 | 
					        self.assertIsNone(kwargs['document_type'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch("documents.serialisers.bulk_edit.add_tag")
 | 
				
			||||||
 | 
					    def test_api_add_tag(self, m):
 | 
				
			||||||
 | 
					        m.return_value = "OK"
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc1.id],
 | 
				
			||||||
 | 
					            "method": "add_tag",
 | 
				
			||||||
 | 
					            "parameters": {"tag": self.t1.id}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        m.assert_called_once()
 | 
				
			||||||
 | 
					        args, kwargs = m.call_args
 | 
				
			||||||
 | 
					        self.assertEqual(args[0], [self.doc1.id])
 | 
				
			||||||
 | 
					        self.assertEqual(kwargs['tag'], self.t1.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch("documents.serialisers.bulk_edit.remove_tag")
 | 
				
			||||||
 | 
					    def test_api_remove_tag(self, m):
 | 
				
			||||||
 | 
					        m.return_value = "OK"
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc1.id],
 | 
				
			||||||
 | 
					            "method": "remove_tag",
 | 
				
			||||||
 | 
					            "parameters": {"tag": self.t1.id}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
 | 
					        m.assert_called_once()
 | 
				
			||||||
 | 
					        args, kwargs = m.call_args
 | 
				
			||||||
 | 
					        self.assertEqual(args[0], [self.doc1.id])
 | 
				
			||||||
 | 
					        self.assertEqual(kwargs['tag'], self.t1.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch("documents.serialisers.bulk_edit.delete")
 | 
				
			||||||
 | 
					    def test_api_delete(self, m):
 | 
				
			||||||
 | 
					        m.return_value = "OK"
 | 
				
			||||||
        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
            "documents": [self.doc1.id],
 | 
					            "documents": [self.doc1.id],
 | 
				
			||||||
            "method": "delete",
 | 
					            "method": "delete",
 | 
				
			||||||
            "parameters": {}
 | 
					            "parameters": {}
 | 
				
			||||||
        }), content_type='application/json')
 | 
					        }), content_type='application/json')
 | 
				
			||||||
        self.assertEqual(response.status_code, 200)
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
        self.assertEqual(Document.objects.count(), 4)
 | 
					        m.assert_called_once()
 | 
				
			||||||
 | 
					        args, kwargs = m.call_args
 | 
				
			||||||
 | 
					        self.assertEqual(args[0], [self.doc1.id])
 | 
				
			||||||
 | 
					        self.assertEqual(len(kwargs), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_api_invalid_doc(self):
 | 
					    def test_api_invalid_doc(self):
 | 
				
			||||||
        self.assertEqual(Document.objects.count(), 5)
 | 
					        self.assertEqual(Document.objects.count(), 5)
 | 
				
			||||||
@@ -727,3 +866,38 @@ class TestBulkEdit(DirectoriesMixin, APITestCase):
 | 
				
			|||||||
        }), content_type='application/json')
 | 
					        }), content_type='application/json')
 | 
				
			||||||
        self.assertEqual(response.status_code, 400)
 | 
					        self.assertEqual(response.status_code, 400)
 | 
				
			||||||
        self.assertEqual(Document.objects.count(), 5)
 | 
					        self.assertEqual(Document.objects.count(), 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_api_invalid_correspondent(self):
 | 
				
			||||||
 | 
					        self.assertEqual(self.doc2.correspondent, self.c1)
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc2.id],
 | 
				
			||||||
 | 
					            "method": "set_correspondent",
 | 
				
			||||||
 | 
					            "parameters": {'correspondent': 345657}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        doc2 = Document.objects.get(id=self.doc2.id)
 | 
				
			||||||
 | 
					        self.assertEqual(doc2.correspondent, self.c1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_api_invalid_document_type(self):
 | 
				
			||||||
 | 
					        self.assertEqual(self.doc2.document_type, self.dt1)
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc2.id],
 | 
				
			||||||
 | 
					            "method": "set_document_type",
 | 
				
			||||||
 | 
					            "parameters": {'document_type': 345657}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        doc2 = Document.objects.get(id=self.doc2.id)
 | 
				
			||||||
 | 
					        self.assertEqual(doc2.document_type, self.dt1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_api_invalid_tag(self):
 | 
				
			||||||
 | 
					        self.assertEqual(list(self.doc2.tags.all()), [self.t1])
 | 
				
			||||||
 | 
					        response = self.client.post("/api/documents/bulk_edit/", json.dumps({
 | 
				
			||||||
 | 
					            "documents": [self.doc2.id],
 | 
				
			||||||
 | 
					            "method": "add_tag",
 | 
				
			||||||
 | 
					            "parameters": {'document_type': 345657}
 | 
				
			||||||
 | 
					        }), content_type='application/json')
 | 
				
			||||||
 | 
					        self.assertEqual(response.status_code, 400)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(list(self.doc2.tags.all()), [self.t1])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,12 @@
 | 
				
			|||||||
import unittest
 | 
					import unittest
 | 
				
			||||||
 | 
					from unittest import mock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.core.checks import Error
 | 
				
			||||||
from django.test import TestCase
 | 
					from django.test import TestCase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .factories import DocumentFactory
 | 
					from .factories import DocumentFactory
 | 
				
			||||||
from ..checks import changed_password_check
 | 
					from .. import document_consumer_declaration
 | 
				
			||||||
 | 
					from ..checks import changed_password_check, parser_check
 | 
				
			||||||
from ..models import Document
 | 
					from ..models import Document
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,3 +18,13 @@ class ChecksTestCase(TestCase):
 | 
				
			|||||||
    def test_changed_password_check_no_encryption(self):
 | 
					    def test_changed_password_check_no_encryption(self):
 | 
				
			||||||
        DocumentFactory.create(storage_type=Document.STORAGE_TYPE_UNENCRYPTED)
 | 
					        DocumentFactory.create(storage_type=Document.STORAGE_TYPE_UNENCRYPTED)
 | 
				
			||||||
        self.assertEqual(changed_password_check(None), [])
 | 
					        self.assertEqual(changed_password_check(None), [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_parser_check(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(parser_check(None), [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with mock.patch('documents.checks.document_consumer_declaration.send') as m:
 | 
				
			||||||
 | 
					            m.return_value = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.assertEqual(parser_check(None), [Error("No parsers found. This is a bug. The consumer won't be "
 | 
				
			||||||
 | 
					                                                        "able to consume any documents without parsers.")])
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user