Complete multiple check in/out support

Signed-off-by: Roberto Rosario <roberto.rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2019-07-12 04:49:39 -04:00
parent d4f7e2cd16
commit e2f2181ebb
8 changed files with 356 additions and 205 deletions
+30 -1
View File
@@ -11,6 +11,7 @@ from mayan.apps.common.menus import (
) )
from mayan.apps.dashboards.dashboards import dashboard_main from mayan.apps.dashboards.dashboards import dashboard_main
from mayan.apps.events.classes import ModelEventType from mayan.apps.events.classes import ModelEventType
from mayan.apps.navigation.classes import SourceColumn
from .dashboard_widgets import DashboardWidgetTotalCheckouts from .dashboard_widgets import DashboardWidgetTotalCheckouts
from .events import ( from .events import (
@@ -46,6 +47,8 @@ class CheckoutsApp(MayanAppConfig):
def ready(self): def ready(self):
super(CheckoutsApp, self).ready() super(CheckoutsApp, self).ready()
CheckedOutDocument = self.get_model(model_name='CheckedOutDocument')
DocumentCheckout = self.get_model(model_name='DocumentCheckout')
Document = apps.get_model( Document = apps.get_model(
app_label='documents', model_name='Document' app_label='documents', model_name='Document'
) )
@@ -79,6 +82,22 @@ class CheckoutsApp(MayanAppConfig):
permission_document_check_out_detail_view permission_document_check_out_detail_view
) )
) )
ModelPermission.register_inheritance(
model=DocumentCheckout, related='document'
)
SourceColumn(
attribute='get_user_display', include_label=True, order=99,
source=CheckedOutDocument
)
SourceColumn(
attribute='get_checkout_datetime', include_label=True, order=99,
source=CheckedOutDocument
)
SourceColumn(
attribute='get_checkout_expiration', include_label=True, order=99,
source=CheckedOutDocument
)
dashboard_main.add_widget( dashboard_main.add_widget(
widget=DashboardWidgetTotalCheckouts, order=-1 widget=DashboardWidgetTotalCheckouts, order=-1
@@ -91,9 +110,19 @@ class CheckoutsApp(MayanAppConfig):
menu_multi_item.bind_links( menu_multi_item.bind_links(
links=( links=(
link_check_in_document_multiple, link_check_in_document_multiple,
link_check_out_document_multiple ), sources=(CheckedOutDocument,)
)
menu_multi_item.bind_links(
links=(
link_check_in_document_multiple,
link_check_out_document_multiple,
), sources=(Document,) ), sources=(Document,)
) )
menu_multi_item.unbind_links(
links=(
link_check_out_document_multiple,
), sources=(CheckedOutDocument,)
)
menu_secondary.bind_links( menu_secondary.bind_links(
links=(link_check_out_document, link_check_in_document), links=(link_check_out_document, link_check_in_document),
sources=( sources=(
+54 -24
View File
@@ -6,6 +6,7 @@ from django.apps import apps
from django.db import models, transaction from django.db import models, transaction
from django.utils.timezone import now from django.utils.timezone import now
from mayan.apps.acls.models import AccessControlList
from mayan.apps.documents.models import Document from mayan.apps.documents.models import Document
from .events import ( from .events import (
@@ -14,10 +15,53 @@ from .events import (
) )
from .exceptions import DocumentNotCheckedOut from .exceptions import DocumentNotCheckedOut
from .literals import STATE_CHECKED_OUT, STATE_CHECKED_IN from .literals import STATE_CHECKED_OUT, STATE_CHECKED_IN
from .permissions import (
permission_document_check_in, permission_document_check_in_override
)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class DocumentCheckoutBusinessLogicManager(models.Manager):
def check_in_document(self, document, user=None):
queryset = document._meta.default_manager.filter(pk=document.pk)
return self.check_in_documents(queryset=queryset, user=user)
def check_in_documents(self, queryset, user=None):
if user:
user_document_checkouts = AccessControlList.objects.restrict_queryset(
permission=permission_document_check_in,
queryset=self.filter(user_id=user.pk, document__in=queryset),
user=user
)
others_document_checkouts = AccessControlList.objects.restrict_queryset(
permission=permission_document_check_in_override,
queryset=self.exclude(user_id=user.pk, document__in=queryset),
user=user
)
with transaction.atomic():
if user:
for checkout in user_document_checkouts:
event_document_check_in.commit(
actor=user, target=checkout.document
)
checkout.delete()
for checkout in others_document_checkouts:
event_document_forceful_check_in.commit(
actor=user, target=checkout.document
)
checkout.delete()
else:
for checkout in self.filter(document__in=queryset):
event_document_auto_check_in.commit(
target=checkout.document
)
checkout.delete()
class DocumentCheckoutManager(models.Manager): class DocumentCheckoutManager(models.Manager):
def are_document_new_versions_allowed(self, document, user=None): def are_document_new_versions_allowed(self, document, user=None):
try: try:
@@ -27,25 +71,6 @@ class DocumentCheckoutManager(models.Manager):
else: else:
return not check_out_info.block_new_version return not check_out_info.block_new_version
def check_in_document(self, document, user=None):
try:
document_check_out = self.model.objects.get(document=document)
except self.model.DoesNotExist:
raise DocumentNotCheckedOut
else:
with transaction.atomic():
if user:
if self.get_check_out_info(document=document).user != user:
event_document_forceful_check_in.commit(
actor=user, target=document
)
else:
event_document_check_in.commit(actor=user, target=document)
else:
event_document_auto_check_in.commit(target=document)
document_check_out.delete()
def check_in_expired_check_outs(self): def check_in_expired_check_outs(self):
for document in self.expired_check_outs(): for document in self.expired_check_outs():
document.check_in() document.check_in()
@@ -57,7 +82,11 @@ class DocumentCheckoutManager(models.Manager):
) )
def checked_out_documents(self): def checked_out_documents(self):
return Document.objects.filter( CheckedOutDocument = apps.get_model(
app_label='checkouts', model_name='CheckedOutDocument'
)
return CheckedOutDocument.objects.filter(
pk__in=self.model.objects.values('document__id') pk__in=self.model.objects.values('document__id')
) )
@@ -74,7 +103,11 @@ class DocumentCheckoutManager(models.Manager):
return STATE_CHECKED_IN return STATE_CHECKED_IN
def expired_check_outs(self): def expired_check_outs(self):
expired_list = Document.objects.filter( CheckedOutDocument = apps.get_model(
app_label='checkouts', model_name='CheckedOutDocument'
)
expired_list = CheckedOutDocument.objects.filter(
pk__in=self.model.objects.filter( pk__in=self.model.objects.filter(
expiration_datetime__lte=now() expiration_datetime__lte=now()
).values_list('document__pk', flat=True) ).values_list('document__pk', flat=True)
@@ -83,9 +116,6 @@ class DocumentCheckoutManager(models.Manager):
return expired_list return expired_list
def get_by_natural_key(self, document_natural_key): def get_by_natural_key(self, document_natural_key):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
try: try:
document = Document.objects.get_by_natural_key(document_natural_key) document = Document.objects.get_by_natural_key(document_natural_key)
except Document.DoesNotExist: except Document.DoesNotExist:
+1 -1
View File
@@ -8,7 +8,7 @@ def method_check_in(self, user=None):
app_label='checkouts', model_name='DocumentCheckout' app_label='checkouts', model_name='DocumentCheckout'
) )
return DocumentCheckout.objects.check_in_document( return DocumentCheckout.business_logic.check_in_document(
document=self, user=user document=self, user=user
) )
+29 -4
View File
@@ -14,7 +14,10 @@ from mayan.apps.documents.models import Document
from .events import event_document_check_out from .events import event_document_check_out
from .exceptions import DocumentAlreadyCheckedOut from .exceptions import DocumentAlreadyCheckedOut
from .managers import DocumentCheckoutManager, NewVersionBlockManager from .managers import (
DocumentCheckoutBusinessLogicManager, DocumentCheckoutManager,
NewVersionBlockManager
)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -49,6 +52,7 @@ class DocumentCheckout(models.Model):
) )
objects = DocumentCheckoutManager() objects = DocumentCheckoutManager()
business_logic = DocumentCheckoutBusinessLogicManager()
class Meta: class Meta:
ordering = ('pk',) ordering = ('pk',)
@@ -81,13 +85,13 @@ class DocumentCheckout(models.Model):
natural_key.dependencies = ['documents.Document'] natural_key.dependencies = ['documents.Document']
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
new_checkout = not self.pk is_new = not self.pk
if not new_checkout or self.document.is_checked_out(): if not is_new or self.document.is_checked_out():
raise DocumentAlreadyCheckedOut raise DocumentAlreadyCheckedOut
with transaction.atomic(): with transaction.atomic():
result = super(DocumentCheckout, self).save(*args, **kwargs) result = super(DocumentCheckout, self).save(*args, **kwargs)
if new_checkout: if is_new:
event_document_check_out.commit( event_document_check_out.commit(
actor=self.user, target=self.document actor=self.user, target=self.document
) )
@@ -119,3 +123,24 @@ class NewVersionBlock(models.Model):
def natural_key(self): def natural_key(self):
return self.document.natural_key() return self.document.natural_key()
natural_key.dependencies = ['documents.Document'] natural_key.dependencies = ['documents.Document']
class CheckedOutDocument(Document):
class Meta:
proxy = True
def get_user_display(self):
check_out_info = self.get_check_out_info()
return check_out_info.user.get_full_name() or check_out_info.user
get_user_display.short_description = _('User')
def get_checkout_datetime(self):
return self.get_check_out_info().checkout_datetime
get_checkout_datetime.short_description = _('Checkout time and date')
def get_checkout_expiration(self):
return self.get_check_out_info().expiration_datetime
get_checkout_expiration.short_description = _('Checkout expiration')
+23 -2
View File
@@ -5,6 +5,7 @@ import datetime
from django.utils.timezone import now from django.utils.timezone import now
from mayan.apps.common.literals import TIME_DELTA_UNIT_DAYS from mayan.apps.common.literals import TIME_DELTA_UNIT_DAYS
from mayan.apps.common.tests.utils import as_id_list
from ..models import DocumentCheckout from ..models import DocumentCheckout
@@ -12,7 +13,10 @@ from ..models import DocumentCheckout
class DocumentCheckoutTestMixin(object): class DocumentCheckoutTestMixin(object):
_test_document_check_out_seconds = 0.1 _test_document_check_out_seconds = 0.1
def _check_out_test_document(self, user=None): def _check_out_test_document(self, document=None, user=None):
if not document:
document = self.test_document
if not user: if not user:
user = self._test_case_user user = self._test_case_user
@@ -21,7 +25,7 @@ class DocumentCheckoutTestMixin(object):
) )
self.test_check_out = DocumentCheckout.objects.check_out_document( self.test_check_out = DocumentCheckout.objects.check_out_document(
block_new_version=True, document=self.test_document, block_new_version=True, document=document,
expiration_datetime=self._check_out_expiration_datetime, expiration_datetime=self._check_out_expiration_datetime,
user=user user=user
) )
@@ -42,6 +46,13 @@ class DocumentCheckoutViewTestMixin(object):
} }
) )
def _request_test_document_multiple_check_in_post_view(self):
return self.post(
viewname='checkouts:check_in_document_multiple', data={
'id_list': as_id_list(items=self.test_documents)
}
)
def _request_test_document_check_out_view(self): def _request_test_document_check_out_view(self):
return self.post( return self.post(
viewname='checkouts:check_out_document', kwargs={ viewname='checkouts:check_out_document', kwargs={
@@ -53,6 +64,16 @@ class DocumentCheckoutViewTestMixin(object):
} }
) )
def _request_test_document_multiple_check_out_post_view(self):
return self.post(
viewname='checkouts:check_out_document_multiple', data={
'block_new_version': True,
'expiration_datetime_0': TIME_DELTA_UNIT_DAYS,
'expiration_datetime_1': 2,
'id_list': as_id_list(items=self.test_documents)
}
)
def _request_test_document_check_out_detail_view(self): def _request_test_document_check_out_detail_view(self):
return self.get( return self.get(
viewname='checkouts:check_out_info', kwargs={ viewname='checkouts:check_out_info', kwargs={
+1 -6
View File
@@ -7,8 +7,7 @@ from mayan.apps.documents.tests import GenericDocumentTestCase, DocumentTestMixi
from mayan.apps.documents.tests.literals import TEST_SMALL_DOCUMENT_PATH from mayan.apps.documents.tests.literals import TEST_SMALL_DOCUMENT_PATH
from ..exceptions import ( from ..exceptions import (
DocumentAlreadyCheckedOut, DocumentNotCheckedOut, DocumentAlreadyCheckedOut, NewDocumentVersionNotAllowed
NewDocumentVersionNotAllowed
) )
from ..models import DocumentCheckout, NewVersionBlock from ..models import DocumentCheckout, NewVersionBlock
@@ -49,10 +48,6 @@ class DocumentCheckoutTestCase(DocumentCheckoutTestMixin, GenericDocumentTestCas
block_new_version=True block_new_version=True
) )
def test_checkin_without_checkout(self):
with self.assertRaises(DocumentNotCheckedOut):
self.test_document.check_in()
def test_auto_check_in(self): def test_auto_check_in(self):
self._check_out_test_document() self._check_out_test_document()
+197 -28
View File
@@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from mayan.apps.common.literals import TIME_DELTA_UNIT_DAYS
from mayan.apps.documents.permissions import permission_document_view from mayan.apps.documents.permissions import permission_document_view
from mayan.apps.documents.tests import GenericDocumentViewTestCase from mayan.apps.documents.tests import GenericDocumentViewTestCase
from mayan.apps.sources.links import link_document_version_upload from mayan.apps.sources.links import link_document_version_upload
@@ -23,8 +22,8 @@ class DocumentCheckoutViewTestCase(
self._check_out_test_document() self._check_out_test_document()
response = self._request_test_document_check_in_get_view() response = self._request_test_document_check_in_get_view()
self.assertContains( self.assertNotContains(
response=response, text=self.test_document.label, status_code=200 response=response, text=self.test_document.label, status_code=404
) )
self.assertTrue(self.test_document.is_checked_out()) self.assertTrue(self.test_document.is_checked_out())
@@ -68,6 +67,86 @@ class DocumentCheckoutViewTestCase(
) )
) )
def test_document_multiple_check_in_post_view_no_permission(self):
# Upload second document
self.upload_document()
self._check_out_test_document(document=self.test_documents[0])
self._check_out_test_document(document=self.test_documents[1])
response = self._request_test_document_multiple_check_in_post_view()
self.assertEqual(response.status_code, 404)
self.assertTrue(self.test_documents[0].is_checked_out())
self.assertTrue(self.test_documents[1].is_checked_out())
self.assertTrue(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[0]
)
)
self.assertTrue(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[1]
)
)
def test_document_multiple_check_in_post_view_with_document_0_access(self):
# Upload second document
self.upload_document()
self._check_out_test_document(document=self.test_documents[0])
self._check_out_test_document(document=self.test_documents[1])
self.grant_access(
obj=self.test_documents[0], permission=permission_document_check_in
)
response = self._request_test_document_multiple_check_in_post_view()
self.assertEqual(response.status_code, 302)
self.assertFalse(self.test_documents[0].is_checked_out())
self.assertTrue(self.test_documents[1].is_checked_out())
self.assertFalse(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[0]
)
)
self.assertTrue(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[1]
)
)
def test_document_multiple_check_in_post_view_with_access(self):
# Upload second document
self.upload_document()
self._check_out_test_document(document=self.test_documents[0])
self._check_out_test_document(document=self.test_documents[1])
self.grant_access(
obj=self.test_documents[0], permission=permission_document_check_in
)
self.grant_access(
obj=self.test_documents[1], permission=permission_document_check_in
)
response = self._request_test_document_multiple_check_in_post_view()
self.assertEqual(response.status_code, 302)
self.assertFalse(self.test_documents[0].is_checked_out())
self.assertFalse(self.test_documents[1].is_checked_out())
self.assertFalse(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[0]
)
)
self.assertFalse(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[1]
)
)
def test_document_check_out_view_no_permission(self): def test_document_check_out_view_no_permission(self):
response = self._request_test_document_check_out_view() response = self._request_test_document_check_out_view()
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@@ -88,6 +167,102 @@ class DocumentCheckoutViewTestCase(
self.assertTrue(self.test_document.is_checked_out()) self.assertTrue(self.test_document.is_checked_out())
def test_document_multiple_check_out_post_view_no_permission(self):
# Upload second document
self.upload_document()
self.grant_access(
obj=self.test_documents[0],
permission=permission_document_check_out_detail_view
)
self.grant_access(
obj=self.test_documents[1],
permission=permission_document_check_out_detail_view
)
response = self._request_test_document_multiple_check_out_post_view()
self.assertEqual(response.status_code, 404)
self.assertFalse(self.test_documents[0].is_checked_out())
self.assertFalse(self.test_documents[1].is_checked_out())
self.assertFalse(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[0]
)
)
self.assertFalse(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[1]
)
)
def test_document_multiple_check_out_post_view_with_document_0_access(self):
# Upload second document
self.upload_document()
self.grant_access(
obj=self.test_documents[0], permission=permission_document_check_out
)
self.grant_access(
obj=self.test_documents[0],
permission=permission_document_check_out_detail_view
)
self.grant_access(
obj=self.test_documents[1],
permission=permission_document_check_out_detail_view
)
response = self._request_test_document_multiple_check_out_post_view()
self.assertEqual(response.status_code, 302)
self.assertTrue(self.test_documents[0].is_checked_out())
self.assertFalse(self.test_documents[1].is_checked_out())
self.assertTrue(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[0]
)
)
self.assertFalse(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[1]
)
)
def test_document_multiple_check_out_post_view_with_access(self):
# Upload second document
self.upload_document()
self.grant_access(
obj=self.test_documents[0], permission=permission_document_check_out
)
self.grant_access(
obj=self.test_documents[1], permission=permission_document_check_out
)
self.grant_access(
obj=self.test_documents[0],
permission=permission_document_check_out_detail_view
)
self.grant_access(
obj=self.test_documents[1],
permission=permission_document_check_out_detail_view
)
response = self._request_test_document_multiple_check_out_post_view()
self.assertEqual(response.status_code, 302)
self.assertTrue(self.test_documents[0].is_checked_out())
self.assertTrue(self.test_documents[1].is_checked_out())
self.assertTrue(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[0]
)
)
self.assertTrue(
DocumentCheckout.objects.is_checked_out(
document=self.test_documents[1]
)
)
def test_document_check_out_detail_view_no_permission(self): def test_document_check_out_detail_view_no_permission(self):
self._check_out_test_document() self._check_out_test_document()
@@ -177,45 +352,39 @@ class DocumentCheckoutViewTestCase(
self.assertEqual(resolved_link, None) self.assertEqual(resolved_link, None)
def test_document_forcefull_check_in_view_no_permission(self): def test_document_check_in_forcefull_view_no_permission(self):
# Gitlab issue #237 # Gitlab issue #237
# Forcefully checking in a document by a user without adequate # Forcefully checking in a document by a user without adequate
# permissions throws out an error # permissions throws out an error
self._create_test_case_superuser() self._create_test_user()
self._check_out_test_document(user=self._test_case_superuser) self._check_out_test_document(user=self.test_user)
self.grant_access( self.grant_access(
obj=self.test_document, permission=permission_document_check_in obj=self.test_document, permission=permission_document_check_in
) )
response = self.post(
viewname='checkouts:check_in_document', kwargs={
'pk': self.test_document.pk
}
)
self.assertContains(
response=response, text='Insufficient permissions', status_code=403
)
self.assertTrue(self.test_document.is_checked_out())
def test_document_forcefull_check_in_view_with_permission(self):
self._create_test_case_superuser()
self._check_out_test_document(user=self._test_case_superuser)
self.grant_access(
obj=self.test_document, permission=permission_document_check_in
)
self.grant_access(
obj=self.test_document, permission=permission_document_check_in_override
)
response = self.post( response = self.post(
viewname='checkouts:check_in_document', kwargs={ viewname='checkouts:check_in_document', kwargs={
'pk': self.test_document.pk 'pk': self.test_document.pk
} }
) )
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
self.assertTrue(self.test_document.is_checked_out())
def test_document_check_in_forcefull_view_with_access(self):
self._create_test_user()
self._check_out_test_document(user=self.test_user)
self.grant_access(
obj=self.test_document,
permission=permission_document_check_in_override
)
response = self.post(
viewname='checkouts:check_in_document', kwargs={
'pk': self.test_document.pk
}
)
self.assertEqual(response.status_code, 302)
self.assertFalse(self.test_document.is_checked_out()) self.assertFalse(self.test_document.is_checked_out())
+21 -139
View File
@@ -1,21 +1,16 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse from django.urls import reverse
from django.utils.translation import ugettext_lazy as _, ungettext from django.utils.translation import ugettext_lazy as _, ungettext
from mayan.apps.acls.models import AccessControlList from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.generics import ( from mayan.apps.common.generics import (
ConfirmView, MultipleObjectConfirmActionView, MultipleObjectFormActionView, MultipleObjectConfirmActionView, MultipleObjectFormActionView,
SingleObjectCreateView, SingleObjectDetailView SingleObjectDetailView
) )
from mayan.apps.common.utils import encapsulate
from mayan.apps.documents.models import Document from mayan.apps.documents.models import Document
from mayan.apps.documents.views import DocumentListView from mayan.apps.documents.views import DocumentListView
from .exceptions import DocumentAlreadyCheckedOut, DocumentNotCheckedOut
from .forms import DocumentCheckoutForm, DocumentCheckoutDefailForm from .forms import DocumentCheckoutForm, DocumentCheckoutDefailForm
from .icons import icon_check_out_info from .icons import icon_check_out_info
from .models import DocumentCheckout from .models import DocumentCheckout
@@ -25,69 +20,9 @@ from .permissions import (
) )
"""
class DocumentCheckinView(ConfirmView):
def get_extra_context(self):
document = self.get_object()
context = {
'object': document,
}
if document.get_check_out_info().user != self.request.user:
context['title'] = _(
'You didn\'t originally checked out this document. '
'Forcefully check in the document: %s?'
) % document
else:
context['title'] = _('Check in the document: %s?') % document
return context
def get_object(self):
return get_object_or_404(klass=Document, pk=self.kwargs['pk'])
def get_post_action_redirect(self):
return reverse(
viewname='checkouts:check_out_info', kwargs={
'pk': self.get_object().pk
}
)
def view_action(self):
document = self.get_object()
if document.get_check_out_info().user == self.request.user:
AccessControlList.objects.check_access(
obj=document, permissions=(permission_document_check_in,),
user=self.request.user
)
else:
AccessControlList.objects.check_access(
obj=document,
permissions=(permission_document_check_in_override,),
user=self.request.user
)
try:
document.check_in(user=self.request.user)
except DocumentNotCheckedOut:
messages.error(
message=_('Document has not been checked out.'),
request=self.request
)
else:
messages.success(
message=_(
'Document "%s" checked in successfully.'
) % document, request=self.request
)
"""
class DocumentCheckinView(MultipleObjectConfirmActionView): class DocumentCheckinView(MultipleObjectConfirmActionView):
error_message = 'Unable to check in document "%(instance)s". %(exception)s' error_message = 'Unable to check in document "%(instance)s". %(exception)s'
model = Document model = Document
object_permission = permission_document_check_in
pk_url_kwarg = 'pk' pk_url_kwarg = 'pk'
success_message_singular = '%(count)d document checked in.' success_message_singular = '%(count)d document checked in.'
success_message_plural = '%(count)d documents checked in.' success_message_plural = '%(count)d documents checked in.'
@@ -126,63 +61,30 @@ class DocumentCheckinView(MultipleObjectConfirmActionView):
else: else:
super(DocumentCheckinView, self).get_post_action_redirect() super(DocumentCheckinView, self).get_post_action_redirect()
def get_source_queryset(self):
# object_permission is None to disable restricting queryset mixin
# and restrict the queryset ourselves from two permissions
source_queryset = super(DocumentCheckinView, self).get_source_queryset()
check_in_queryset = AccessControlList.objects.restrict_queryset(
permission=permission_document_check_in, queryset=source_queryset,
user=self.request.user
)
check_in_override_queryset = AccessControlList.objects.restrict_queryset(
permission=permission_document_check_in_override,
queryset=source_queryset, user=self.request.user
)
return check_in_queryset | check_in_override_queryset
def object_action(self, form, instance): def object_action(self, form, instance):
DocumentCheckout.objects.check_in_document( DocumentCheckout.business_logic.check_in_document(
document=instance, user=self.request.user document=instance, user=self.request.user
) )
"""
class CheckoutDocumentView(SingleObjectCreateView):
form_class = DocumentCheckoutForm
def dispatch(self, request, *args, **kwargs):
self.document = get_object_or_404(klass=Document, pk=self.kwargs['pk'])
AccessControlList.objects.check_access(
obj=self.document, permissions=(permission_document_check_out,),
user=request.user
)
return super(
CheckoutDocumentView, self
).dispatch(request, *args, **kwargs)
def form_valid(self, form):
try:
instance = form.save(commit=False)
instance.user = self.request.user
instance.document = self.document
instance.save()
except DocumentAlreadyCheckedOut:
messages.error(
message=_('Document already checked out.'),
request=self.request
)
else:
messages.success(
message=_(
'Document "%s" checked out successfully.'
) % self.document, request=self.request
)
return HttpResponseRedirect(redirect_to=self.get_success_url())
def get_extra_context(self):
return {
'object': self.document,
'title': _('Check out document: %s') % self.document
}
def get_post_action_redirect(self):
return reverse(
viewname='checkouts:check_out_info', kwargs={
'pk': self.document.pk
}
)
"""
class DocumentCheckoutView(MultipleObjectFormActionView): class DocumentCheckoutView(MultipleObjectFormActionView):
error_message = 'Unable to checkout document "%(instance)s". %(exception)s' error_message = 'Unable to checkout document "%(instance)s". %(exception)s'
form_class = DocumentCheckoutForm form_class = DocumentCheckoutForm
@@ -261,26 +163,6 @@ class DocumentCheckoutListView(DocumentListView):
context = super(DocumentCheckoutListView, self).get_extra_context() context = super(DocumentCheckoutListView, self).get_extra_context()
context.update( context.update(
{ {
'extra_columns': (
{
'name': _('User'),
'attribute': encapsulate(
lambda document: document.get_check_out_info().user.get_full_name() or document.get_check_out_info().user
)
},
{
'name': _('Checkout time and date'),
'attribute': encapsulate(
lambda document: document.get_check_out_info().checkout_datetime
)
},
{
'name': _('Checkout expiration'),
'attribute': encapsulate(
lambda document: document.get_check_out_info().expiration_datetime
)
},
),
'no_results_icon': icon_check_out_info, 'no_results_icon': icon_check_out_info,
'no_results_text': _( 'no_results_text': _(
'Checking out a document, blocks certain operations ' 'Checking out a document, blocks certain operations '