Files
mayan-edms/mayan/apps/cabinets/models.py
Roberto Rosario 36a51eeb73 Switch to full app paths
Instead of inserting the path of the apps into the Python app,
the apps are now referenced by their full import path.

This solves name clashes with external or native Python libraries.
Example: Mayan statistics app vs. Python new statistics library.

Every app reference is now prepended with 'mayan.apps'.

Existing config.yml files need to be updated manually.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
2019-04-05 02:02:57 -04:00

109 lines
3.8 KiB
Python

from __future__ import absolute_import, unicode_literals
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
from django.db import connection, models, transaction
from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from mptt.fields import TreeForeignKey
from mptt.models import MPTTModel
from mayan.apps.acls.models import AccessControlList
from mayan.apps.documents.models import Document
from mayan.apps.documents.permissions import permission_document_view
from .events import event_cabinets_add_document, event_cabinets_remove_document
from .search import cabinet_search # NOQA
@python_2_unicode_compatible
class Cabinet(MPTTModel):
parent = TreeForeignKey(
blank=True, db_index=True, null=True, on_delete=models.CASCADE,
related_name='children', to='self'
)
label = models.CharField(max_length=128, verbose_name=_('Label'))
documents = models.ManyToManyField(
blank=True, related_name='cabinets', to=Document,
verbose_name=_('Documents')
)
class Meta:
ordering = ('parent__label', 'label')
# unique_together doesn't work if there is a FK
# https://code.djangoproject.com/ticket/1751
unique_together = ('parent', 'label')
verbose_name = _('Cabinet')
verbose_name_plural = _('Cabinets')
def __str__(self):
return self.get_full_path()
def add_document(self, document, user=None):
self.documents.add(document)
event_cabinets_add_document.commit(
action_object=self, actor=user, target=document
)
def get_absolute_url(self):
return reverse('cabinets:cabinet_view', args=(self.pk,))
def get_document_count(self, user):
return self.get_documents_queryset(user=user).count()
def get_documents_queryset(self, user):
return AccessControlList.objects.filter_by_access(
permission_document_view, user, queryset=self.documents
)
def get_full_path(self):
result = []
for node in self.get_ancestors(include_self=True):
result.append(node.label)
return ' / '.join(result)
def remove_document(self, document, user=None):
self.documents.remove(document)
event_cabinets_remove_document.commit(
action_object=self, actor=user, target=document
)
def validate_unique(self, exclude=None):
# Explicit validation of uniqueness of parent+label as the provided
# unique_together check in Meta is not working for all 100% cases
# when there is a FK in the unique_together tuple
# https://code.djangoproject.com/ticket/1751
with transaction.atomic():
if connection.vendor == 'oracle':
queryset = Cabinet.objects.filter(parent=self.parent, label=self.label)
else:
queryset = Cabinet.objects.select_for_update().filter(parent=self.parent, label=self.label)
if queryset.exists():
params = {
'model_name': _('Cabinet'),
'field_labels': _('Parent and Label')
}
raise ValidationError(
{
NON_FIELD_ERRORS: [
ValidationError(
message=_(
'%(model_name)s with this %(field_labels)s already '
'exists.'
), code='unique_together', params=params,
)
],
},
)
class DocumentCabinet(Cabinet):
class Meta:
proxy = True
verbose_name = _('Document cabinet')
verbose_name_plural = _('Document cabinets')