diff --git a/mayan/apps/checkouts/api_views.py b/mayan/apps/checkouts/api_views.py index e1052ddfef..01b90511ae 100644 --- a/mayan/apps/checkouts/api_views.py +++ b/mayan/apps/checkouts/api_views.py @@ -31,7 +31,7 @@ class APICheckedoutDocumentListView(generics.ListCreateAPIView): return DocumentCheckoutSerializer def get_queryset(self): - documents = DocumentCheckout.objects.checked_out_documents() + documents = DocumentCheckout.on_organization.checked_out_documents() try: Permission.check_permissions( @@ -44,7 +44,7 @@ class APICheckedoutDocumentListView(generics.ListCreateAPIView): else: filtered_documents = documents - return DocumentCheckout.objects.filter( + return DocumentCheckout.on_organization.filter( document__pk__in=filtered_documents.values_list('pk', flat=True) ) @@ -80,7 +80,7 @@ class APICheckedoutDocumentListView(generics.ListCreateAPIView): timezone = pytz.utc try: - DocumentCheckout.objects.create( + DocumentCheckout.on_organization.create( document=document, expiration_datetime=timezone.localize( serializer.data['expiration_datetime'] @@ -104,7 +104,7 @@ class APICheckedoutDocumentView(generics.RetrieveDestroyAPIView): def get_queryset(self): if self.request.method == 'GET': - documents = DocumentCheckout.objects.checked_out_documents() + documents = DocumentCheckout.on_organization.checked_out_documents() try: Permission.check_permissions( @@ -117,13 +117,13 @@ class APICheckedoutDocumentView(generics.RetrieveDestroyAPIView): else: filtered_documents = documents - return DocumentCheckout.objects.filter( + return DocumentCheckout.on_organization.filter( document__pk__in=filtered_documents.values_list( 'pk', flat=True ) ) elif self.request.method == 'DELETE': - return DocumentCheckout.objects.all() + return DocumentCheckout.on_organization.all() def get(self, request, *args, **kwargs): """ diff --git a/mayan/apps/checkouts/apps.py b/mayan/apps/checkouts/apps.py index e1f27f0eba..f2872e72d9 100644 --- a/mayan/apps/checkouts/apps.py +++ b/mayan/apps/checkouts/apps.py @@ -43,23 +43,23 @@ class CheckoutsApp(MayanAppConfig): Document.add_to_class( 'check_in', - lambda document, user=None: DocumentCheckout.objects.check_in_document(document, user) + lambda document, user=None: DocumentCheckout.on_organization.check_in_document(document, user) ) Document.add_to_class( 'checkout_info', - lambda document: DocumentCheckout.objects.document_checkout_info( + lambda document: DocumentCheckout.on_organization.document_checkout_info( document ) ) Document.add_to_class( 'checkout_state', - lambda document: DocumentCheckout.objects.document_checkout_state( + lambda document: DocumentCheckout.on_organization.document_checkout_state( document ) ) Document.add_to_class( 'is_checked_out', - lambda document: DocumentCheckout.objects.is_document_checked_out( + lambda document: DocumentCheckout.on_organization.is_document_checked_out( document ) ) diff --git a/mayan/apps/checkouts/managers.py b/mayan/apps/checkouts/managers.py index cb10095132..f18b1a5e04 100644 --- a/mayan/apps/checkouts/managers.py +++ b/mayan/apps/checkouts/managers.py @@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals import logging +from django.apps import apps from django.db import models from django.utils.timezone import now @@ -26,14 +27,14 @@ class DocumentCheckoutManager(models.Manager): def checked_out_documents(self): return Document.on_organization.filter( - pk__in=self.model.objects.all().values_list( + pk__in=self.all().values_list( 'document__pk', flat=True ) ) def expired_check_outs(self): expired_list = Document.on_organization.filter( - pk__in=self.model.objects.filter( + pk__in=self.filter( expiration_datetime__lte=now() ).values_list('document__pk', flat=True) ) @@ -45,14 +46,14 @@ class DocumentCheckoutManager(models.Manager): document.check_in() def is_document_checked_out(self, document): - if self.model.objects.filter(document=document): + if self.model.on_organization.filter(document=document): return True else: return False def check_in_document(self, document, user=None): try: - document_checkout = self.model.objects.get(document=document) + document_checkout = self.get(document=document) except self.model.DoesNotExist: raise DocumentNotCheckedOut else: @@ -70,7 +71,7 @@ class DocumentCheckoutManager(models.Manager): def document_checkout_info(self, document): try: - return self.model.objects.get(document=document) + return self.get(document=document) except self.model.DoesNotExist: raise DocumentNotCheckedOut @@ -87,3 +88,14 @@ class DocumentCheckoutManager(models.Manager): return True else: return not checkout_info.block_new_version + + +class OrganizationDocumentCheckoutManager(DocumentCheckoutManager): + def get_queryset(self): + Document = apps.get_model('documents', 'Document') + + return super( + OrganizationDocumentCheckoutManager, self + ).get_queryset().filter( + document__in=Document.on_organization.all() + ) diff --git a/mayan/apps/checkouts/models.py b/mayan/apps/checkouts/models.py index 45ec9e81b8..2f3de53216 100644 --- a/mayan/apps/checkouts/models.py +++ b/mayan/apps/checkouts/models.py @@ -14,7 +14,9 @@ from documents.models import Document, NewVersionBlock from .events import event_document_check_out from .exceptions import DocumentAlreadyCheckedOut -from .managers import DocumentCheckoutManager +from .managers import ( + DocumentCheckoutManager, OrganizationDocumentCheckoutManager +) logger = logging.getLogger(__name__) @@ -44,6 +46,11 @@ class DocumentCheckout(models.Model): ) objects = DocumentCheckoutManager() + on_organization = OrganizationDocumentCheckoutManager() + + class Meta: + verbose_name = _('Document checkout') + verbose_name_plural = _('Document checkouts') def __str__(self): return unicode(self.document) @@ -82,7 +89,3 @@ class DocumentCheckout(models.Model): ) return result - - class Meta: - verbose_name = _('Document checkout') - verbose_name_plural = _('Document checkouts') diff --git a/mayan/apps/checkouts/serializers.py b/mayan/apps/checkouts/serializers.py index 72f7947cca..4705b5c2ef 100644 --- a/mayan/apps/checkouts/serializers.py +++ b/mayan/apps/checkouts/serializers.py @@ -2,14 +2,13 @@ from __future__ import unicode_literals from rest_framework import serializers +from documents.serializers import DocumentSerializer + from .models import DocumentCheckout class DocumentCheckoutSerializer(serializers.ModelSerializer): def __init__(self, *args, **kwargs): - # Hide this import otherwise strange circular import error occur - from documents.serializers import DocumentSerializer - super(DocumentCheckoutSerializer, self).__init__(*args, **kwargs) self.fields['document'] = DocumentSerializer() diff --git a/mayan/apps/checkouts/tasks.py b/mayan/apps/checkouts/tasks.py index 046c9a8e40..605ff95f17 100644 --- a/mayan/apps/checkouts/tasks.py +++ b/mayan/apps/checkouts/tasks.py @@ -29,7 +29,7 @@ def task_check_expired_check_outs(): name=lock_id, timeout=CHECKOUT_EXPIRATION_LOCK_EXPIRE ) logger.debug('acquired lock: %s', lock_id) - DocumentCheckout.objects.check_in_expired_check_outs() + DocumentCheckout.on_organization.check_in_expired_check_outs() lock.release() except LockError: logger.debug('unable to obtain lock') diff --git a/mayan/apps/checkouts/tests/test_models.py b/mayan/apps/checkouts/tests/test_models.py index 3502253236..3c239bff86 100644 --- a/mayan/apps/checkouts/tests/test_models.py +++ b/mayan/apps/checkouts/tests/test_models.py @@ -25,12 +25,12 @@ from ..models import DocumentCheckout class DocumentCheckoutTestCase(OrganizationTestCase): def setUp(self): super(DocumentCheckoutTestCase, self).setUp() - self.admin_user = get_user_model().objects.create_superuser( + self.admin_user = get_user_model().on_organization.create_superuser( username=TEST_ADMIN_USERNAME, email=TEST_ADMIN_EMAIL, password=TEST_ADMIN_PASSWORD ) - self.document_type = DocumentType.objects.create( + self.document_type = DocumentType.on_organization.create( label=TEST_DOCUMENT_TYPE ) @@ -46,14 +46,14 @@ class DocumentCheckoutTestCase(OrganizationTestCase): def test_document_checkout(self): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True ) self.assertTrue(self.document.is_checked_out()) self.assertTrue( - DocumentCheckout.objects.is_document_checked_out( + DocumentCheckout.on_organization.is_document_checked_out( document=self.document ) ) @@ -61,7 +61,7 @@ class DocumentCheckoutTestCase(OrganizationTestCase): def test_version_creation_blocking(self): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True ) @@ -73,7 +73,7 @@ class DocumentCheckoutTestCase(OrganizationTestCase): def test_checkin_in(self): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True ) @@ -82,7 +82,7 @@ class DocumentCheckoutTestCase(OrganizationTestCase): self.assertFalse(self.document.is_checked_out()) self.assertFalse( - DocumentCheckout.objects.is_document_checked_out( + DocumentCheckout.on_organization.is_document_checked_out( document=self.document ) ) @@ -90,13 +90,13 @@ class DocumentCheckoutTestCase(OrganizationTestCase): def test_double_checkout(self): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True ) with self.assertRaises(DocumentAlreadyCheckedOut): - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True @@ -109,13 +109,13 @@ class DocumentCheckoutTestCase(OrganizationTestCase): def test_auto_checkin(self): expiration_datetime = now() + datetime.timedelta(seconds=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True ) time.sleep(2) - DocumentCheckout.objects.check_in_expired_check_outs() + DocumentCheckout.on_organization.check_in_expired_check_outs() self.assertFalse(self.document.is_checked_out()) diff --git a/mayan/apps/checkouts/tests/test_organization_views.py b/mayan/apps/checkouts/tests/test_organization_views.py new file mode 100644 index 0000000000..0928de240c --- /dev/null +++ b/mayan/apps/checkouts/tests/test_organization_views.py @@ -0,0 +1,103 @@ +from __future__ import unicode_literals + +import datetime + +from django.utils.timezone import now + +from common.literals import TIME_DELTA_UNIT_DAYS +from documents.models import DocumentType +from documents.tests.literals import ( + TEST_DOCUMENT_TYPE, TEST_SMALL_DOCUMENT_PATH +) +from organizations.tests.test_organization_views import OrganizationViewTestCase + +from ..models import DocumentCheckout + +#from .literals import ( +# TEST_DOCUMENT_METADATA_VALUE_2, TEST_METADATA_TYPE_LABEL, +# TEST_METADATA_TYPE_LABEL_2, TEST_METADATA_TYPE_NAME, +# TEST_METADATA_TYPE_NAME_2 +#) + + +class OrganizationDocumentCheckoutTestCase(OrganizationViewTestCase): + def create_document(self): + with self.settings(ORGANIZATION_ID=self.organization_a.pk): + self.document_type = DocumentType.on_organization.create( + label=TEST_DOCUMENT_TYPE + ) + + with open(TEST_SMALL_DOCUMENT_PATH) as file_object: + self.document = self.document_type.new_document( + file_object=file_object + ) + + def check_out_document(self): + self.create_document() + expiration_datetime = now() + datetime.timedelta(days=1) + + with self.settings(ORGANIZATION_ID=self.organization_a.pk): + + DocumentCheckout.on_organization.checkout_document( + document=self.document, + expiration_datetime=expiration_datetime, user=self.user, + block_new_version=True + ) + + def test_checkout_info(self): + self.check_out_document() + + with self.settings(ORGANIZATION_ID=self.organization_a.pk): + response = self.get( + 'checkouts:checkout_info', args=(self.document.pk,), + follow=True + ) + + self.assertEquals(response.status_code, 200) + + with self.settings(ORGANIZATION_ID=self.organization_b.pk): + response = self.get( + 'checkouts:checkout_info', args=(self.document.pk,), + follow=True + ) + + self.assertEquals(response.status_code, 404) + + def test_check_in(self): + self.check_out_document() + + with self.settings(ORGANIZATION_ID=self.organization_b.pk): + response = self.get( + 'checkouts:checkin_document', args=(self.document.pk,), + follow=True + ) + + self.assertEquals(response.status_code, 404) + with self.settings(ORGANIZATION_ID=self.organization_a.pk): + self.assertTrue(self.document.is_checked_out()) + + def test_check_out(self): + self.create_document() + + with self.settings(ORGANIZATION_ID=self.organization_b.pk): + response = self.post( + 'checkouts:checkout_document', args=(self.document.pk,), data={ + 'expiration_datetime_0': 2, + 'expiration_datetime_1': TIME_DELTA_UNIT_DAYS, + 'block_new_version': True + }, follow=True + ) + + self.assertEquals(response.status_code, 404) + with self.settings(ORGANIZATION_ID=self.organization_a.pk): + self.assertFalse(self.document.is_checked_out()) + + def test_checkout_list(self): + self.check_out_document() + + with self.settings(ORGANIZATION_ID=self.organization_b.pk): + response = self.get('checkouts:checkout_list') + + self.assertNotContains( + response, text=self.document.label, status_code=200 + ) diff --git a/mayan/apps/checkouts/tests/test_views.py b/mayan/apps/checkouts/tests/test_views.py index 294f9f4438..5e17714412 100644 --- a/mayan/apps/checkouts/tests/test_views.py +++ b/mayan/apps/checkouts/tests/test_views.py @@ -27,7 +27,7 @@ class DocumentCheckoutViewTestCase(GenericDocumentViewTestCase): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.user, block_new_version=True ) @@ -49,7 +49,7 @@ class DocumentCheckoutViewTestCase(GenericDocumentViewTestCase): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.user, block_new_version=True ) @@ -72,7 +72,7 @@ class DocumentCheckoutViewTestCase(GenericDocumentViewTestCase): self.assertFalse(self.document.is_checked_out()) self.assertFalse( - DocumentCheckout.objects.is_document_checked_out( + DocumentCheckout.on_organization.is_document_checked_out( document=self.document ) ) @@ -134,7 +134,7 @@ class DocumentCheckoutViewTestCase(GenericDocumentViewTestCase): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True ) @@ -169,7 +169,7 @@ class DocumentCheckoutViewTestCase(GenericDocumentViewTestCase): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True ) @@ -200,7 +200,7 @@ class DocumentCheckoutViewTestCase(GenericDocumentViewTestCase): def test_forcefull_check_in_document_view_with_permission(self): expiration_datetime = now() + datetime.timedelta(days=1) - DocumentCheckout.objects.checkout_document( + DocumentCheckout.on_organization.checkout_document( document=self.document, expiration_datetime=expiration_datetime, user=self.admin_user, block_new_version=True ) diff --git a/mayan/apps/checkouts/views.py b/mayan/apps/checkouts/views.py index 0c4b7dfe73..daa22b5892 100644 --- a/mayan/apps/checkouts/views.py +++ b/mayan/apps/checkouts/views.py @@ -103,7 +103,7 @@ class CheckoutListView(DocumentListView): } def get_document_queryset(self): - return DocumentCheckout.objects.checked_out_documents() + return DocumentCheckout.on_organization.checked_out_documents() class CheckoutDetailView(SingleObjectDetailView):