Files
mayan-edms/mayan/apps/documents/managers.py
Roberto Rosario 64e1c6bb67 Add widget support to SourceColumn
Allow passing a widget class to SourceColumn. This makes
using lambdas to render model column unnecesary and are
mostly removed too.

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
2018-12-22 05:35:31 -04:00

285 lines
9.8 KiB
Python

from __future__ import unicode_literals
from datetime import timedelta
import logging
from django.apps import apps
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models import F, Max
from django.utils.encoding import force_text
from django.utils.timezone import now
from .literals import STUB_EXPIRATION_INTERVAL
from .settings import setting_favorite_count, setting_recent_access_count
logger = logging.getLogger(__name__)
class DocumentManager(models.Manager):
def get_by_natural_key(self, uuid):
return self.model.passthrough.get(uuid=force_text(uuid))
def get_queryset(self):
return TrashCanQuerySet(
self.model, using=self._db
).filter(in_trash=False).filter(is_stub=False)
def invalidate_cache(self):
for document in self.model.objects.all():
document.invalidate_cache()
class DocumentPageManager(models.Manager):
def get_by_natural_key(self, page_number, document_version_natural_key):
DocumentVersion = apps.get_model(
app_label='documents', model_name='DocumentVersion'
)
try:
document_version = DocumentVersion.objects.get_by_natural_key(*document_version_natural_key)
except DocumentVersion.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document_version__pk=document_version.pk, page_number=page_number)
class DocumentTypeManager(models.Manager):
def check_delete_periods(self):
logger.info('Executing')
for document_type in self.all():
logger.info(
'Checking deletion period of document type: %s', document_type
)
if document_type.delete_time_period and document_type.delete_time_unit:
delta = timedelta(
**{
document_type.delete_time_unit: document_type.delete_time_period
}
)
logger.info(
'Document type: %s, has a deletion period delta of: %s',
document_type, delta
)
for document in document_type.deleted_documents.filter(deleted_date_time__lt=now() - delta):
logger.info(
'Document "%s" with id: %d, trashed on: %s, exceded '
'delete period', document, document.pk,
document.deleted_date_time
)
document.delete()
else:
logger.info(
'Document type: %s, has a no retention delta', document_type
)
logger.info('Finshed')
def check_trash_periods(self):
logger.info('Executing')
for document_type in self.all():
logger.info(
'Checking trash period of document type: %s', document_type
)
if document_type.trash_time_period and document_type.trash_time_unit:
delta = timedelta(
**{
document_type.trash_time_unit: document_type.trash_time_period
}
)
logger.info(
'Document type: %s, has a trash period delta of: %s',
document_type, delta
)
for document in document_type.documents.filter(date_added__lt=now() - delta):
logger.info(
'Document "%s" with id: %d, added on: %s, exceded '
'trash period', document, document.pk,
document.date_added
)
document.delete()
else:
logger.info(
'Document type: %s, has a no retention delta', document_type
)
logger.info('Finshed')
def get_by_natural_key(self, label):
return self.get(label=label)
class DocumentVersionManager(models.Manager):
def get_by_natural_key(self, checksum, document_natural_key):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
try:
document = Document.objects.get_by_natural_key(*document_natural_key)
except Document.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document__pk=document.pk, checksum=checksum)
class DuplicatedDocumentManager(models.Manager):
def clean_empty_duplicate_lists(self):
self.filter(documents=None).delete()
def get_duplicated_documents(self):
DuplicatedDocumentProxy = apps.get_model(
app_label='documents', model_name='DuplicatedDocumentProxy'
)
return DuplicatedDocumentProxy.objects.filter(
pk__in=self.filter(documents__isnull=False).values_list(
'document_id', flat=True
)
)
def scan(self):
"""
Find duplicates by iterating over all documents and then
find matching latest version checksums
"""
Document = apps.get_model(
app_label='documents', model_name='Document'
)
for document in Document.objects.all():
self.scan_for(document=document, scan_children=False)
def scan_for(self, document, scan_children=True):
"""
Find duplicates by matching latest version checksums
"""
if not document.latest_version:
return None
Document = apps.get_model(
app_label='documents', model_name='Document'
)
# Get the documents whose latest version matches the checksum
# of the current document and exclude the current document
duplicates = Document.objects.annotate(
max_timestamp=Max('versions__timestamp')
).filter(
versions__timestamp=F('max_timestamp'),
versions__checksum=document.checksum
).exclude(pk=document.pk)
if duplicates.exists():
instance, created = self.get_or_create(document=document)
instance.documents.add(*duplicates)
else:
self.filter(document=document).delete()
if scan_children:
for document in duplicates:
self.scan_for(document=document, scan_children=False)
class FavoriteDocumentManager(models.Manager):
def add_for_user(self, user, document):
favorite_document, created = self.model.objects.get_or_create(
user=user, document=document
)
old_favorites_to_delete = self.filter(user=user).values_list('pk', flat=True)[setting_favorite_count.value:]
self.filter(pk__in=list(old_favorites_to_delete)).delete()
def get_by_natural_key(self, datetime_accessed, document_natural_key, user_natural_key):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
User = get_user_model()
try:
document = Document.objects.get_by_natural_key(*document_natural_key)
except Document.DoesNotExist:
raise self.model.DoesNotExist
else:
try:
user = User.objects.get_by_natural_key(*user_natural_key)
except User.DoesNotExist:
raise self.model.DoesNotExist
return self.get(document__pk=document.pk, user__pk=user.pk)
def get_for_user(self, user):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
return Document.objects.filter(favorites__user=user)
def remove_for_user(self, user, document):
self.get(user=user, document=document).delete()
class PassthroughManager(models.Manager):
def delete_stubs(self):
for stale_stub_document in self.filter(is_stub=True, date_added__lt=now() - timedelta(seconds=STUB_EXPIRATION_INTERVAL)):
stale_stub_document.delete(to_trash=False)
class RecentDocumentManager(models.Manager):
def add_document_for_user(self, user, document):
if user.is_authenticated:
new_recent, created = self.model.objects.get_or_create(
user=user, document=document
)
if not created:
# document already in the recent list, just save to force
# accessed date and time update
new_recent.save()
recent_to_delete = self.filter(user=user).values_list('pk', flat=True)[setting_recent_access_count.value:]
self.filter(pk__in=list(recent_to_delete)).delete()
return new_recent
def get_by_natural_key(self, datetime_accessed, document_natural_key, user_natural_key):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
User = get_user_model()
try:
document = Document.objects.get_by_natural_key(*document_natural_key)
except Document.DoesNotExist:
raise self.model.DoesNotExist
else:
try:
user = User.objects.get_by_natural_key(*user_natural_key)
except User.DoesNotExist:
raise self.model.DoesNotExist
return self.get(
document__pk=document.pk, user__pk=user.pk,
datetime_accessed=datetime_accessed
)
def get_for_user(self, user):
Document = apps.get_model(
app_label='documents', model_name='Document'
)
if user.is_authenticated:
return Document.objects.filter(
recent__user=user
).order_by('-recent__datetime_accessed')
else:
return Document.objects.none()
class TrashCanManager(models.Manager):
def get_queryset(self):
return super(
TrashCanManager, self
).get_queryset().filter(in_trash=True)
class TrashCanQuerySet(models.QuerySet):
def delete(self, to_trash=True):
for instance in self:
instance.delete(to_trash=to_trash)