diff --git a/HISTORY.rst b/HISTORY.rst index 1a5bc6f31b..78d99a7645 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -46,6 +46,7 @@ - Add support for subscribing to the events of a tag. - Add the tag events view permissions to the tag model ACL. - Hide the title link of documents in the trash. +- Add support for document metadata events: add, edit and remove. 3.0.1 (2018-07-08) diff --git a/mayan/apps/metadata/api.py b/mayan/apps/metadata/api.py index e64505c248..ed641f7a14 100644 --- a/mayan/apps/metadata/api.py +++ b/mayan/apps/metadata/api.py @@ -35,28 +35,37 @@ def decode_metadata_from_querystring(querystring=None): return metadata_list -def save_metadata_list(metadata_list, document, create=False): +def save_metadata_list(metadata_list, document, create=False, _user=None): """ Take a list of metadata dictionaries and associate them to a document """ for item in metadata_list: - save_metadata(item, document, create) + save_metadata( + metadata_dict=item, document=document, create=create, _user=_user + ) -def save_metadata(metadata_dict, document, create=False): +def save_metadata(metadata_dict, document, create=False, _user=None): """ Take a dictionary of metadata type & value and associate it to a document """ + parameters = { + 'document': document, + 'metadata_type': get_object_or_404( + MetadataType, + pk=metadata_dict['id'] + ) + } + if create: # Use matched metadata now to create document metadata - document_metadata, created = DocumentMetadata.objects.get_or_create( - document=document, - metadata_type=get_object_or_404( - MetadataType, - pk=metadata_dict['id']) - ) + try: + DocumentMetadata.objects.get(**parameters) + except DocumentMetadata.DoesNotExist: + document_metadata = DocumentMetadata(**parameters) + document_metadata.save(_user=_user) else: try: document_metadata = DocumentMetadata.objects.get( @@ -77,7 +86,7 @@ def save_metadata(metadata_dict, document, create=False): # .decode('utf-8') if document_metadata: document_metadata.value = unquote_plus(metadata_dict['value']) - document_metadata.save() + document_metadata.save(_user=_user) def metadata_repr(metadata_list): diff --git a/mayan/apps/metadata/apps.py b/mayan/apps/metadata/apps.py index 9f2cdb47a6..dc9439c26b 100644 --- a/mayan/apps/metadata/apps.py +++ b/mayan/apps/metadata/apps.py @@ -28,8 +28,9 @@ from navigation import SourceColumn from .classes import DocumentMetadataHelper from .events import ( - event_metadata_type_created, event_metadata_type_edited, - event_metadata_type_relationship + event_document_metadata_added, event_document_metadata_edited, + event_document_metadata_removed,event_metadata_type_created, + event_metadata_type_edited, event_metadata_type_relationship ) from .handlers import ( handler_index_document, post_document_type_metadata_type_add, @@ -112,13 +113,30 @@ class MetadataApp(MayanAppConfig): type_name=['property', 'indexing'] ) + ModelEventType.register( + model=Document, event_types=( + event_document_metadata_added, + event_document_metadata_edited, + event_document_metadata_removed, + ) + ) + ModelEventType.register( model=MetadataType, event_types=( + event_document_metadata_added, + event_document_metadata_edited, + event_document_metadata_removed, event_metadata_type_edited, event_metadata_type_relationship, ) ) + ModelEventType.register( + model=DocumentType, event_types=( + event_metadata_type_relationship, + ) + ) + ModelPermission.register( model=Document, permissions=( permission_metadata_document_add, diff --git a/mayan/apps/metadata/events.py b/mayan/apps/metadata/events.py index 628324eb4f..23b2ca7633 100644 --- a/mayan/apps/metadata/events.py +++ b/mayan/apps/metadata/events.py @@ -6,6 +6,21 @@ from events import EventTypeNamespace namespace = EventTypeNamespace(name='metadata', label=_('Metadata')) +event_document_metadata_added = namespace.add_event_type( + name='document_metadata_added', label=_( + 'Document metadata added' + ) +) +event_document_metadata_edited = namespace.add_event_type( + name='document_metadata_edited', label=_( + 'Document metadata edited' + ) +) +event_document_metadata_removed = namespace.add_event_type( + name='document_metadata_removed', label=_( + 'Document metadata removed' + ) +) event_metadata_type_created = namespace.add_event_type( name='metadata_type_created', label=_('Metadata type created') ) @@ -17,3 +32,4 @@ event_metadata_type_relationship = namespace.add_event_type( 'Metadata type relationship updated' ) ) + diff --git a/mayan/apps/metadata/models.py b/mayan/apps/metadata/models.py index 1dce6d3dc0..0dc2ee7cd6 100644 --- a/mayan/apps/metadata/models.py +++ b/mayan/apps/metadata/models.py @@ -5,6 +5,7 @@ import shlex from django.core.exceptions import ValidationError from django.db import models from django.template import Context, Template +from django.urls import reverse, reverse_lazy from django.utils.encoding import force_text, python_2_unicode_compatible from django.utils.module_loading import import_string from django.utils.translation import ugettext_lazy as _ @@ -13,8 +14,9 @@ from documents.models import Document, DocumentType from .classes import MetadataLookup from .events import ( - event_metadata_type_created, event_metadata_type_edited, - event_metadata_type_relationship + event_document_metadata_added, event_document_metadata_edited, + event_document_metadata_removed,event_metadata_type_created, + event_metadata_type_edited, event_metadata_type_relationship ) from .managers import DocumentTypeMetadataTypeManager, MetadataTypeManager from .settings import setting_available_parsers, setting_available_validators @@ -91,6 +93,9 @@ class MetadataType(models.Model): def __str__(self): return self.label + def get_absolute_url(self): + return reverse('metadata:setup_metadata_type_edit', args=(self.pk,)) + @staticmethod def comma_splitter(string): splitter = shlex.shlex(string.encode('utf-8'), posix=True) @@ -208,7 +213,13 @@ class DocumentMetadata(models.Model): _('Metadata type is required for this document type.') ) - return super(DocumentMetadata, self).delete(*args, **kwargs) + user = kwargs.pop('_user', None) + result = super(DocumentMetadata, self).delete(*args, **kwargs) + + event_document_metadata_removed.commit( + action_object=self.metadata_type, actor=user, target=self.document, + ) + return result def natural_key(self): return self.document.natural_key() + self.metadata_type.natural_key() @@ -226,7 +237,23 @@ class DocumentMetadata(models.Model): _('Metadata type is not valid for this document type.') ) - return super(DocumentMetadata, self).save(*args, **kwargs) + user = kwargs.pop('_user', None) + created = not self.pk + + result = super(DocumentMetadata, self).save(*args, **kwargs) + + if created: + event_document_metadata_added.commit( + action_object=self.metadata_type, actor=user, + target=self.document, + ) + else: + event_document_metadata_edited.commit( + action_object=self.metadata_type, actor=user, + target=self.document, + ) + + return result @python_2_unicode_compatible diff --git a/mayan/apps/metadata/views.py b/mayan/apps/metadata/views.py index b0b89339d0..76ff225062 100644 --- a/mayan/apps/metadata/views.py +++ b/mayan/apps/metadata/views.py @@ -149,11 +149,19 @@ class DocumentMetadataAddView(MultipleObjectFormActionView): def object_action(self, form, instance): for metadata_type in form.cleaned_data['metadata_type']: try: - document_metadata, created = DocumentMetadata.objects.get_or_create( - document=instance, - metadata_type=metadata_type, - defaults={'value': ''} - ) + created = False + try: + DocumentMetadata.objects.get( + document=instance, + metadata_type=metadata_type, + ) + except DocumentMetadata.DoesNotExist: + instance = DocumentMetadata( + document=instance, + metadata_type=metadata_type, + ) + instance.save(_user=self.request.user) + created = True except ValidationError as exception: messages.error( self.request, @@ -310,7 +318,10 @@ class DocumentMetadataEditView(MultipleObjectFormActionView): for form in form.forms: if form.cleaned_data['update']: try: - save_metadata_list([form.cleaned_data], instance) + save_metadata_list( + metadata_list=[form.cleaned_data], document=instance, + _user=self.request.user + ) except Exception as exception: errors.append(exception) @@ -488,7 +499,7 @@ class DocumentMetadataRemoveView(MultipleObjectFormActionView): document_metadata = DocumentMetadata.objects.get( document=instance, metadata_type=metadata_type ) - document_metadata.delete() + document_metadata.delete(_user=self.request.user) messages.success( self.request, _(