def pay_by_ponderation(self, operator, recipient, ponderation_price): """ Procède au paiement de l'évenement par les participants. Une seule vente, un seul paiement mais plusieurs débits sur compte (un par participant) :param operator: user qui procède au paiement :param recipient: user qui recoit les paiements (AE_ENSAM) :param ponderation_price: price per ponderation for each participant :return: """ self.done = True self.save() for e in self.weightsuser_set.all(): weight = e.weights_participation if weight != 0: user_price = ponderation_price * weight e.user.debit(user_price) recipient.credit(user_price) if (e.user.balance < 0): # If negative balance after event # We notify notify(notification_class_name='negative_balance', actor=operator, recipient=e.user, target_object=self) self.payment_by_ponderation = True self.price = ponderation_price self.datetime = now() self.remark = 'Paiement par Borgia (Prix par pondération: ' + \ str(ponderation_price) + ')' self.save()
def create(self, request): if self.check_valid_vote(self.request.user, self.request.POST['comment']): vote = CommentVote( vote=True if self.request.POST.get('vote') == 'up' else False, user=self.request.user, date_voted=timezone.now(), comment=CustomComment.objects.get( pk=self.request.POST['comment'])) vote.save() action.send( request.user, action_object=vote.comment, verb=_(u"voted on"), vote=True if request.POST.get('vote') == 'up' else False) suff = "up" if vote.vote else "down" notify(request.user, vote.comment.user, action_object=vote, action_target=vote.comment, verb=_(u"voted {} for your comment".format(suff)), key="vote") return Response({'success': True, 'message': _('Vote saved')}) else: return Response({ 'success': False, 'message': _('Already voted on this comment') })
def comment_notification(sender, instance, created, **kwargs): """ Send notification for commented object creator. Handles special case of task participants, when we want to notify them all at once. """ if not created or instance.parent is not None: # this is edited comment or answer for other comment # They have their own hooks in places_core.actions. return True if instance.content_object.__class__.__name__ == 'Task': # Special case - send notifications to all task participants for user in instance.content_object.participants.exclude( pk=instance.user.pk): notify(instance.user, user, key="comment", verb=_(u"commented task"), action_object=instance, action_target=instance.content_object) # Get target user to notify depending on commented object's type. target_user = None if hasattr(instance.content_object, 'creator'): # Regular content objects usually have 'creator' field target_user = instance.content_object.creator elif hasattr(instance.content_object, 'author'): # Projects and some other models that use other convention target_user = instance.content_object.author # Notify users only when someone else commented their objects. if target_user is not None and instance.user != target_user: notify(instance.user, target_user, key="customcomment", verb="commented your", action_object=instance, action_target=instance.content_object)
def add_follower(request, pk): """ Add user to locations followers. """ location = get_object_or_404(Location, pk=pk) user = request.user location.users.add(user) if user != location.creator: notify(user, location.creator, verb=_(u"joined to your location"), key="follower", action_target=location ) try: location.save() follow(user, location, actor_only = False) response = { 'success': True, 'message': _('You follow this location'), } except: response = { 'success': False, 'message': _('Something, somewhere went terribly wrong'), } return HttpResponse(json.dumps(response))
def create(self, request): if self.check_valid_vote(self.request.user, self.request.POST['comment']): vote = CommentVote(vote=True if self.request.POST.get('vote') == 'up' else False, user=self.request.user, date_voted = timezone.now(), comment=CustomComment.objects.get(pk=self.request.POST['comment'])) vote.save() action.send( request.user, action_object=vote.comment, verb= _(u"voted on"), vote = True if request.POST.get('vote') == 'up' else False ) suff = "up" if vote.vote else "down" notify( request.user, vote.comment.user, action_object=vote, action_target=vote.comment, verb=_(u"voted {} for your comment".format(suff)), key="vote" ) return Response({ 'success': True, 'message': _('Vote saved') }) else: return Response({ 'success': False, 'message': _('Already voted on this comment') })
def comment_action_hook(sender, instance, created, **kwargs): """ Action hook for comments - inform other people about the fact that this comment was created and increase the amount of user points accordingly. """ if not created: return True prof = UserProfile.objects.get(user=instance.user) prof.rank_pts += 3 prof.save() # Send action for user and location activity streams action.send( instance.user, action_object = instance, target = instance.content_object, verb = _(u"commented"), comment = instance.comment, comment_url = instance.content_object.get_absolute_url() ) # Send notification to parent comment author (if this is answer for comment) if instance.parent is not None: notify( instance.user, instance.parent.user, key="customcomment", verb=_(u"answered your comment"), action_object=instance, action_target=instance.parent )
def post(self, request, *args, **kwargs): """Accept or reject transmittal.""" self.object = self.get_object() action = request.POST.get('action', None) if action == 'reject': method = getattr(self.object, 'reject') success_msg = 'The transmittal {} was sucessfully rejected.'.format( self.object) error_msg = 'We failed to process rejection of transmittal {}. ' \ 'Please contact an administrator.'.format(self.object) elif action == 'accept': method = getattr(self.object, 'accept') success_msg = 'The transmittal {} is currently being processed.'.format( self.object) error_msg = 'We failed to process the import of transmittal {}. ' \ 'Please contact an administrator.'.format(self.object) try: method() notify(request.user, success_msg) return HttpResponseRedirect(reverse('transmittal_list')) except Exception as e: error_msg = '{} ({})'.format(error_msg, e) notify(request.user, error_msg) logger.error(e) return HttpResponseRedirect( reverse('transmittal_diff', args=[self.object.pk, self.object.document_key]))
def comment_action_hook(sender, instance, created, **kwargs): """ Action hook for comments - inform other people about the fact that this comment was created and increase the amount of user points accordingly. """ if not created: return True if instance.content_object.__class__.__name__ == 'Marker': # Disable notification and action for map markers on votings. return True prof = UserProfile.objects.get(user=instance.user) prof.rank_pts += 3 prof.save() # Send action for user and location activity streams action.send(instance.user, action_object=instance, target=instance.content_object, verb=_(u"commented"), comment=instance.comment, comment_url=instance.content_object.get_absolute_url()) # Send notification to parent comment author (if this is answer for comment) # but only when we don't respond to if instance.parent is not None and instance.parent.user != instance.user: notify(instance.user, instance.parent.user, key="customcomment", verb=_(u"answered your comment"), action_object=instance, action_target=instance.parent)
def comment_notification(sender, instance, created, **kwargs): """ Send notification for commented object creator. Handles special case of task participants, when we want to notify them all at once. """ if not created or instance.parent is not None: # this is edited comment or answer for other comment # They have their own hooks in places_core.actions. return True if instance.content_object.__class__.__name__ == 'Task': # Special case - send notifications to all task participants for user in instance.content_object.participants.exclude( pk=instance.user.pk): notify(instance.user, user, key="comment", verb=_(u"commented task"), action_object=instance, action_target=instance.content_object) target_user = None if hasattr(instance.content_object, 'creator'): target_user = instance.content_object.creator elif hasattr(instance.content_object, 'author'): target_user = instance.content_object.author if target_user is not None and instance.user != target_user: notify(instance.user, target_user, key="customcomment", verb=_(u"commented your {}".format( instance.content_object._meta.verbose_name.title())), action_object=instance, action_target=instance.content_object)
def post(self, request, *args, **kwargs): """Accept or reject transmittal.""" self.object = self.get_object() action = request.POST.get('action', None) if action == 'reject': method = getattr(self.object, 'reject') success_msg = 'The transmittal {} was sucessfully rejected.'.format( self.object) error_msg = 'We failed to process rejection of transmittal {}. ' \ 'Please contact an administrator.'.format(self.object) elif action == 'accept': method = getattr(self.object, 'accept') success_msg = 'The transmittal {} is currently being processed.'.format( self.object) error_msg = 'We failed to process the import of transmittal {}. ' \ 'Please contact an administrator.'.format(self.object) try: method() notify(request.user, success_msg) return HttpResponseRedirect(reverse('transmittal_list')) except Exception as e: error_msg = '{} ({})'.format(error_msg, e) notify(request.user, error_msg) logger.error(e) return HttpResponseRedirect(reverse( 'transmittal_diff', args=[self.object.pk, self.object.document_key]))
def pay(self, operator, recipient): """ Procède au paiement de l'évenement par les participants. Une seule vente, un seul paiement mais plusieurs débits sur compte (un par participant) :param operator: user qui procède au paiement :param recipient: user qui recoit les paiements (AE_ENSAM) :return: """ # Calcul du prix par weight total_weight = self.get_total_weights_participants() final_price_per_weight = round(self.price / total_weight, 2) for e in self.weightsuser_set.all(): e.user.debit(final_price_per_weight * e.weights_participation) if (e.user.balance < 0): # If negative balance after event # We notify notify(notification_class_name='negative_balance', actor=operator, recipient=e.user, target_object=self ) self.done = True self.datetime = now() self.remark = 'Paiement par Borgia' self.save()
def post(self, request, *args, **kwargs): if not self.request.user.is_external: return HttpResponseForbidden( 'Only contractors can acknowledge receipt of transmittals') document_ids = request.POST.getlist('document_ids') transmittals = self.get_queryset() \ .filter(document_id__in=document_ids) \ .filter(ack_of_receipt_date__isnull=True) revision_ids = list( transmittals.values_list('latest_revision_id', flat=True)) # Update transmittal data transmittals.update( ack_of_receipt_date=timezone.now(), ack_of_receipt_author=self.request.user) # Update ES index _revision_class = self.category.revision_class() revisions = _revision_class.objects.filter(id__in=revision_ids) index_revisions(revisions) update_count = len(revision_ids) if update_count > 0: msg = _('You have successfully acknowledged receipt ' 'of %s transmittals.') % update_count else: msg = _('We failed to acknowledge receipt of any transmittal.') notify(self.request.user, msg) return HttpResponseRedirect(self.get_redirect_url())
def add_follower(request, pk): """ Add user to locations followers. """ location = get_object_or_404(Location, pk=pk) user = request.user location.users.add(user) if user != location.creator: notify(user, location.creator, verb=_(u"joined to your location"), key="follower", action_target=location ) try: location.save() follow(user, location, actor_only=False) response = { 'success': True, 'message': _('You follow this location'), } except: response = { 'success': False, 'message': _('Something, somewhere went terribly wrong'), } return HttpResponse(json.dumps(response))
def pay(self, operator, recipient): """ Procède au paiement de l'évenement par les participants. Une seule vente, un seul paiement mais plusieurs débits sur compte (un par participant) :param operator: user qui procède au paiement :param recipient: user qui recoit les paiements (AE_ENSAM) :return: """ # Calcul du prix par weight total_weight = self.get_total_weights_participants() final_price_per_weight = round(self.price / total_weight, 2) for e in self.weightsuser_set.all(): e.user.debit(final_price_per_weight * e.weights_participation) if (e.user.balance < 0): # If negative balance after event # We notify notify(notification_class_name='negative_balance', actor=operator, recipient=e.user, target_object=self) self.done = True self.datetime = now() self.remark = 'Paiement par Borgia' self.save()
def post(self, request, *args, **kwargs): if not self.request.user.is_external: return HttpResponseForbidden( 'Only contractors can acknowledge receipt of transmittals') document_ids = request.POST.getlist('document_ids') transmittals = self.get_queryset() \ .filter(document_id__in=document_ids) \ .filter(ack_of_receipt_date__isnull=True) revision_ids = list( transmittals.values_list('latest_revision_id', flat=True)) # Update transmittal data transmittals.update(ack_of_receipt_date=timezone.now(), ack_of_receipt_author=self.request.user) # Update ES index _revision_class = self.category.revision_class() revisions = _revision_class.objects.filter(id__in=revision_ids) index_revisions(revisions) update_count = len(revision_ids) if update_count > 0: msg = _('You have successfully acknowledged receipt ' 'of %s transmittals.') % update_count else: msg = _('We failed to acknowledge receipt of any transmittal.') notify(self.request.user, msg) return HttpResponseRedirect(self.get_redirect_url())
def form_valid(self, document_form, revision_form): """Saves both the document and it's revision.""" doc, metadata, revision = save_document_forms( document_form, revision_form, self.category, created_by=self.request.user) message_text = '''You created the document <a href="%(url)s">%(key)s (%(title)s)</a>''' message_data = { 'url': doc.get_absolute_url(), 'key': doc.document_key, 'title': doc.title } notify(self.request.user, _(message_text) % message_data) activity_log.send( verb='created', target=None, action_object=doc, sender=None, actor=self.request.user) return HttpResponseRedirect(self.get_success_url())
def form_valid(self, form): return_value = super(ExportCreate, self).form_valid(form) self.object.start_export(user_pk=self.request.user.pk) message = _("Your export is being processed and will be available " "soon.") notify(self.object.owner, message) return return_value
def notify_about_news_deletion(sender, instance, **kwargs): """ Notify newss author about that his news was deleted. """ # For now we assume that only superuser could delete news entries. admin = User.objects.filter(is_superuser=True)[0] notify(admin, instance.creator, key="deletion", verb="deleted your blog entry", action_object=instance )
def form_valid(self, form): self.success_url = reverse('url_notificationtemplate_list', kwargs={'group_name': self.group.name}) # We notify notify(notification_class_name='notification_template_creation', actor=self.request.user) return super(NotificationTemplateCreateView, self).form_valid(form)
def notify_about_news_deletion(sender, instance, **kwargs): """ Notify newss author about that his news was deleted. """ # For now we assume that only superuser could delete news entries. admin = User.objects.filter(is_superuser=True)[0] notify(admin, instance.creator, key="deletion", verb=_(u"deleted your blog entry - {}".format(instance.title)), action_object=instance )
def form_valid(self, form): response = super(FileUpload, self).form_valid(form) do_import.delay(self.object.uid) message_text = """You required the import of a new file. Results <a href="%(url)s">should be available in a few seconds.</a>""" message_data = {"url": self.object.get_absolute_url()} notify(self.request.user, _(message_text) % message_data) return response
def vote_notification(sender, instance, created, **kwargs): """ Notify users that someone voted for their ideas. """ if instance.user == instance.idea.creator or not created: return True suff = "up" if instance.status == 1 else "down" notify(instance.user, instance.idea.creator, key="vote", verb="voted for your idea", action_object=instance, action_target=instance.idea)
def response_notification(sender, instance, created, **kwargs): """ Notify discussion creator about every new answer. """ if not created or instance.creator == instance.discussion.creator: return True notify(instance.creator, instance.discussion.creator, key="answer", verb=_(u"answered for your discussion"), action_object=instance, action_target=instance.discussion)
def form_valid(self, document_form, revision_form): """Saves both the document and it's revision.""" doc, metadata, revision = save_document_forms(document_form, revision_form, self.category) message_text = """You created the document <a href="%(url)s">%(key)s (%(title)s)</a>""" message_data = {"url": doc.get_absolute_url(), "key": doc.document_key, "title": doc.title} notify(self.request.user, _(message_text) % message_data) return HttpResponseRedirect(self.get_success_url())
def response_notification(sender, instance, created, **kwargs): """ Notify discussion creator about every new answer. """ if not created or instance.creator == instance.discussion.creator: return True notify(instance.creator, instance.discussion.creator, key="answer", verb=_(u"answered for your discussion"), action_object=instance, action_target=instance.discussion )
def batch_cancel_reviews(user_id, category_id, contenttype_id, document_ids): contenttype = ContentType.objects.get_for_id(contenttype_id) document_class = contenttype.model_class() docs = document_class.objects \ .select_related() \ .filter(document__category_id=category_id) \ .filter(document_id__in=document_ids) ok = [] nok = [] counter = float(1) nb_reviews = docs.count() for doc in docs: # Update progress counter progress = counter / nb_reviews * 100 current_task.update_state( state='PROGRESS', meta={'progress': progress}) try: if not doc.latest_revision.is_under_review(): raise RuntimeError() doc.latest_revision.cancel_review() user = User.objects.get(pk=user_id) activity_log.send(verb=Activity.VERB_CANCELLED_REVIEW, target=doc.latest_revision, sender=batch_cancel_reviews, actor=user) ok.append(doc) except: # noqa nok.append(doc) counter += 1 if len(ok) > 0: ok_message = ugettext('You canceled the review for the following documents:') ok_list = '</li><li>'.join('<a href="%s">%s</a>' % (doc.get_absolute_url(), doc) for doc in ok) notify(user_id, '{} <ul><li>{}</li></ul>'.format( ok_message, ok_list )) if len(nok) > 0: nok_message = ugettext("We failed to cancel the review for the following documents:") nok_list = '</li><li>'.join('<a href="%s">%s</a>' % (doc.get_absolute_url(), doc) for doc in nok) notify(user_id, '{} <ul><li>{}</li></ul>'.format( nok_message, nok_list )) return 'done'
def finished_task(user, task): """ The user has finished the task. """ task_action(user, task, _(u"finished task")) for participant in task.participants.all(): notify(user, participant, verb=_(u"finished task"), key="project", action_tartget=task)
def joined_to_project(user, project): """ To this function we pass django user instance and project. """ if user != project.creator: action.send(user, verb=_(u"joined to project"), target=project) notify(user, project.creator, verb=_(u"joined to your project"), key="follower", action_target=project )
def joined_to_task(user, task): """ The user has joined the task. """ if user != task.creator: task_action(user, task, _(u"joined to task")) notify(user, task.creator, verb=_(u"joined to your task"), key="follower", action_target=task )
def finished_task(user, task): """ The user has finished the task. """ task_action(user, task, _(u"finished task")) for participant in task.participants.all(): notify(user, participant, verb=_(u"finished task"), key="project", action_tartget=task )
def batch_cancel_reviews(user_id, category_id, contenttype_id, document_ids): contenttype = ContentType.objects.get_for_id(contenttype_id) document_class = contenttype.model_class() docs = document_class.objects \ .select_related() \ .filter(document__category_id=category_id) \ .filter(document_id__in=document_ids) ok = [] nok = [] counter = float(1) nb_reviews = docs.count() for doc in docs: # Update progress counter progress = counter / nb_reviews * 100 current_task.update_state(state='PROGRESS', meta={'progress': progress}) try: if not doc.latest_revision.is_under_review(): raise RuntimeError() doc.latest_revision.cancel_review() user = User.objects.get(pk=user_id) activity_log.send(verb=Activity.VERB_CANCELLED_REVIEW, target=doc.latest_revision, sender=batch_cancel_reviews, actor=user) ok.append(doc) except: # noqa nok.append(doc) counter += 1 if len(ok) > 0: ok_message = ugettext( 'You canceled the review for the following documents:') ok_list = '</li><li>'.join('<a href="%s">%s</a>' % (doc.get_absolute_url(), doc) for doc in ok) notify(user_id, '{} <ul><li>{}</li></ul>'.format(ok_message, ok_list)) if len(nok) > 0: nok_message = ugettext( "We failed to cancel the review for the following documents:") nok_list = '</li><li>'.join('<a href="%s">%s</a>' % (doc.get_absolute_url(), doc) for doc in nok) notify(user_id, '{} <ul><li>{}</li></ul>'.format(nok_message, nok_list)) return 'done'
def vote_notification(sender, instance, created, **kwargs): """ Notify users that someone voted for their ideas. """ if instance.user == instance.idea.creator or not created: return True suff = "up" if instance.vote else "down" notify(instance.user, instance.idea.creator, key="vote", verb=_(u"voted %s for your idea" % suff), action_object=instance, action_target=instance.idea)
def vote_notification(sender, instance, created, **kwargs): """ Notify entry author about votes for his/her entry. """ if not created: return True suff = "up" if instance.vote else "down" notify(instance.user, instance.entry.creator, key="vote", verb=_(u"voted for %s your entry" % suff), action_object=instance, action_target=instance.entry)
def joined_to_task(user, task): """ The user has joined the task. """ if user != task.creator: task_action(user, task, _(u"joined to task")) notify(user, task.creator, verb=_(u"joined to your task"), key="follower", action_target=task)
def vote_notification(sender, instance, created, **kwargs): """ Notify entry author about votes for his/her entry. """ if not created: return True suff = "up" if instance.vote else "down" notify(instance.user, instance.entry.creator, key="vote", verb=_(u"voted for %s your entry" % suff), action_object=instance, action_target=instance.entry )
def joined_to_project(user, project): """ To this function we pass django user instance and project. """ if user != project.creator: action.send(user, verb=_(u"joined to project"), target=project) notify(user, project.creator, verb=_(u"joined to your project"), key="follower", action_target=project)
def notify_mentionned_users(self): """Parse @mentions and create according notifications.""" message = _('%(user)s mentionned you on document ' '<a href="%(url)s">%(doc)s</a> (revision %(revision)02d)') % { 'user': self.author.name, 'url': self.document.get_absolute_url(), 'doc': self.document.document_key, 'revision': int(self.revision) } users = self.parse_mentions() for user in users: notify(user, message)
def form_valid(self, form): response = super(FileUpload, self).form_valid(form) do_import.delay(self.object.uid) message_text = '''You required the import of a new file. Results <a href="%(url)s">should be available in a few seconds.</a>''' message_data = { 'url': self.object.get_absolute_url(), } notify(self.request.user, _(message_text) % message_data) return response
def notify_mentionned_users(self): """Parse @mentions and create according notifications.""" message = _( '%(user)s mentionned you on document ' '<a href="%(url)s">%(doc)s</a> (revision %(revision)02d)') % { 'user': self.author.name, 'url': self.document.get_absolute_url(), 'doc': self.document.document_key, 'revision': int(self.revision) } users = self.parse_mentions() for user in users: notify(user, message)
def process_export(export_id): from exports.models import Export export = Export.objects.select_related().get(id=export_id) export.status = 'processing' export.save() export.write_file() export.status = 'done' export.save() url = export.get_absolute_url() message = _('The export <a href="{}">you required for category {} is ready</a>.'.format( url, export.category)) notify(export.owner, message)
def form_valid(self, form): self.success_url = reverse('url_notificationtemplate_change', kwargs={ 'group_name': self.group.name, 'pk': self.object.pk }) # We notify notify(notification_class_name='notification_template_update', actor=self.request.user) return super(NotificationTemplateUpdateView, self).form_valid(form)
def mention_notify(comment): """ Notify mentioned users when comment is created. """ for match in userreg.finditer(comment.comment): try: user = User.objects.get(username=match.groups()[0]) except User.DoesNotExist: user = None if user is not None and user != comment.user: notify(comment.user, user, key="customcomment", verb=NOTIFY_VERB, action_target=comment)
def post(self, request, **kwargs): form = self.form_class(request.POST) if not form.is_valid(): context = self.get_context_data() context['form'] = form return render(request, self.template_name, context) for user in User.objects.filter(email__in=form.cleaned_data['emails']): if not self.location in user.profile.mod_areas.all(): user.profile.mod_areas.add(self.location) user.profile.save() notify(self.request.user, user, verb=_(u"Granted you moderator access to"), action_target=self.location) messages.add_message(request, messages.SUCCESS, _(u"Success")) return redirect(self.get_success_url())
def post(self, request, *args, **kwargs): notification_template = NotificationTemplate.objects.get( pk=kwargs['pk']) if notification_template.is_activated is True: notification_template.is_activated = False else: notification_template.is_activated = True notification_template.save() self.success_url = reverse('url_notificationtemplate_list', kwargs={'group_name': self.group.name}) # We notify notify(notification_class_name='notification_template_deactivation', actor=self.request.user) return redirect(force_text(self.success_url))
def post(self, request, *args, **kwargs): self.metadata = self.get_object() revision = self.metadata.latest_revision document = self.metadata.document if revision.is_under_review(): revision.cancel_review() message_text = '''You cancelled the review on revision %(rev)s of the document <a href="%(url)s">%(key)s (%(title)s)</a>''' message_data = { 'rev': revision.name, 'url': document.get_absolute_url(), 'key': document.document_key, 'title': document.title } notify(request.user, _(message_text) % message_data) return HttpResponseRedirect(self.get_redirect_url())
def do_create_transmittal( user_id, from_category_id, to_category_id, document_ids, contract_number, purpose_of_issue, recipients_ids): # Display a small amount of progression # so the user won't get impatient current_task.update_state( state='PROGRESS', meta={'progress': 10}) from_category = Category.objects.get(pk=from_category_id) to_category = Category.objects.get(pk=to_category_id) recipients = Entity.objects.filter(pk__in=recipients_ids) documents = Document.objects \ .select_related() \ .filter(id__in=document_ids) revisions = [] for doc in documents: revisions.append(doc.get_latest_revision()) try: for recipient in recipients: doc, _, _ = create_transmittal( from_category, to_category, revisions, contract_number, recipient, purpose_of_issue=purpose_of_issue) msg = '''You successfully created transmittal <a href="{}">{}</a>'''.format(doc.get_absolute_url(), doc) notify(user_id, msg) user = User.objects.get(pk=user_id) activity_log.send(verb=Activity.VERB_CREATED, action_object=doc, sender=None, actor=user) except TransmittalError as e: msg = '''We failed to create a transmittal for the following reason: "{}".'''.format(e) notify(user_id, msg) return 'done'
def do_create_transmittal( user_id, from_category_id, to_category_id, document_ids, contract_number, recipients_ids): # Display a small amount of progression # so the user won't get impatient current_task.update_state( state='PROGRESS', meta={'progress': 10}) from_category = Category.objects.get(pk=from_category_id) to_category = Category.objects.get(pk=to_category_id) recipients = Entity.objects.filter(pk__in=recipients_ids) documents = Document.objects \ .select_related() \ .filter(id__in=document_ids) revisions = [] for doc in documents: revisions.append(doc.get_latest_revision()) try: for recipient in recipients: doc, _, _ = create_transmittal( from_category, to_category, revisions, contract_number, recipient) msg = '''You successfully created transmittal <a href="{}">{}</a>'''.format(doc.get_absolute_url(), doc) notify(user_id, msg) user = User.objects.get(pk=user_id.pk) activity_log.send(verb=Activity.VERB_CREATED, action_object=doc, sender=None, actor=user) except TransmittalError as e: msg = '''We failed to create a transmittal for the following reason: "{}".'''.format(e) notify(user_id, msg) return 'done'
def post(self, request, *args, **kwargs): self.metadata = self.get_object() revision = self.metadata.latest_revision document = self.metadata.document if revision.can_be_reviewed: revision.start_review() # If a non empty message body was submitted... body = self.request.POST.get('body', None) if body: Note.objects.create( author=self.request.user, document=document, revision=revision.revision, body=body) message_text = '''You started the review on revision %(rev)s of the document <a href="%(url)s">%(key)s (%(title)s)</a>''' message_data = { 'rev': revision.name, 'url': document.get_absolute_url(), 'key': document.document_key, 'title': document.title } notify(request.user, _(message_text) % message_data) activity_log.send(verb=Activity.VERB_STARTED_REVIEW, action_object=revision, sender=None, actor=self.request.user) else: message_text = '''The review on revision %(rev)s of the document <a href="%(url)s">%(key)s (%(title)s)</a> cannot be started''' message_data = { 'rev': revision.name, 'url': document.get_absolute_url(), 'key': document.document_key, 'title': document.title } notify(request.user, _(message_text) % message_data) return HttpResponseRedirect(self.get_redirect_url())
def post(self, request, *args, **kwargs): self.metadata = self.get_object() revision = self.metadata.latest_revision document = self.metadata.document if revision.can_be_reviewed: revision.start_review() # If a non empty message body was submitted... body = self.request.POST.get('body', None) if body: Note.objects.create(author=self.request.user, document=document, revision=revision.revision, body=body) message_text = '''You started the review on revision %(rev)s of the document <a href="%(url)s">%(key)s (%(title)s)</a>''' message_data = { 'rev': revision.name, 'url': document.get_absolute_url(), 'key': document.document_key, 'title': document.title } notify(request.user, _(message_text) % message_data) activity_log.send(verb=Activity.VERB_STARTED_REVIEW, action_object=revision, sender=None, actor=self.request.user) else: message_text = '''The review on revision %(rev)s of the document <a href="%(url)s">%(key)s (%(title)s)</a> cannot be started''' message_data = { 'rev': revision.name, 'url': document.get_absolute_url(), 'key': document.document_key, 'title': document.title } notify(request.user, _(message_text) % message_data) return HttpResponseRedirect(self.get_redirect_url())
def created_gallery(user, instance): """ Send action about new gallery. Takes ContentObjectGallery as argument. """ verb = _(u"created gallery") publisher = instance.published_in if publisher is None: action.send(user, verb=verb, action_object=instance) action.send(user, verb=verb, action_object=instance, target=publisher) if hasattr(publisher, 'creator'): target_user = publisher.creator elif hasattr(publisher, 'author'): target_user = publisher.author if target_user == user: return True notify(user, target_user, verb=verb, key="gallery", action_object=instance, action_target=publisher)
def form_valid(self, document_form, revision_form): """Saves both the document and it's revision.""" document, self.object, self.revision = save_document_forms( document_form, revision_form, self.category) message_text = '''You created revision %(rev)s for document <a href="%(url)s">%(key)s (%(title)s)</a>''' message_data = { 'rev': self.revision.name, 'url': self.object.get_absolute_url(), 'key': self.object.document_key, 'title': self.object.title } notify(self.request.user, _(message_text) % message_data) activity_log.send(verb=Activity.VERB_CREATED, target=self.revision, sender=None, actor=self.request.user) return HttpResponseRedirect(self.get_success_url())
def post(self, request, *args, **kwargs): self.metadata = self.get_object() revision = self.metadata.latest_revision document = self.metadata.document if revision.is_under_review(): revision.cancel_review() message_text = '''You cancelled the review on revision %(rev)s of the document <a href="%(url)s">%(key)s (%(title)s)</a>''' message_data = { 'rev': revision.name, 'url': document.get_absolute_url(), 'key': document.document_key, 'title': document.title } notify(request.user, _(message_text) % message_data) activity_log.send(verb=Activity.VERB_CANCELLED_REVIEW, target=revision, sender=None, actor=self.request.user) return HttpResponseRedirect(self.get_redirect_url())
def comment_notification(sender, instance, created, **kwargs): """ Send notification for commented object creator. Handles special case of task participants, when we want to notify them all at once. """ if not created or instance.parent is not None: # this is edited comment or answer for other comment # They have their own hooks in places_core.actions. return True if instance.content_object.__class__.__name__ == 'Task': # Special case - send notifications to all task participants for user in instance.content_object.participants.exclude( pk=instance.user.pk): notify(instance.user, user, key="comment", verb=_(u"commented task"), action_object=instance, action_target=instance.content_object) if instance.content_object.__class__.__name__ == 'Marker': # Special case - map markers for votes. return True # Get target user to notify depending on commented object's type. target_user = None if hasattr(instance.content_object, 'creator'): # Regular content objects usually have 'creator' field target_user = instance.content_object.creator elif hasattr(instance.content_object, 'author'): # Projects and some other models that use other convention target_user = instance.content_object.author # Notify users only when someone else commented their objects. if target_user is not None and instance.user != target_user: notify(instance.user, target_user, key="customcomment", verb="commented your", action_object=instance, action_target=instance.content_object)
def do_batch_import(user_id, category_id, contenttype_id, document_ids, remark=None): # Fetch document list contenttype = ContentType.objects.get_for_id(contenttype_id) document_class = contenttype.model_class() docs = document_class.objects \ .select_related() \ .filter(document__category_id=category_id) \ .filter(document_id__in=document_ids) ok = [] nok = [] count = 0 total_docs = docs.count() # We compute the progress as the proportion of documents for which the # review has started. # However, after all documents are treated, there is still the # index + refresh step which takes quite some time. So we artificially # increase the document count as a hackish way to never display a 100% # progress bar as long as the task is not truly finished. total_docs += 30 pre_batch_review.send(sender=do_batch_import) # Try to start the review for every listed document for doc in docs: try: if not doc.latest_revision.can_be_reviewed: raise RuntimeError() doc.latest_revision.start_review() user = User.objects.get(pk=user_id) activity_log.send(verb=Activity.VERB_STARTED_REVIEW, target=doc.latest_revision, sender=do_batch_import, actor=user) # In case of batch review start with a remark, # the same remark is added for every review. # Note: using "bulk_create" to create all the discussion # at the end of the task would be much more efficient. # However, by doing so, individual `post_save` signals would not # be fired. Since the request is expected to take some time anyway, # we will let this as is for now. if remark: Note.objects.create( author_id=user_id, document_id=doc.document.id, revision=doc.latest_revision.revision, body=remark) batch_item_indexed.send( sender=do_batch_import, document_type=doc.document.document_type(), document_id=doc.id, json=doc.latest_revision.to_json()) ok.append(doc) except: # noqa nok.append(doc) # Update the task progression bar count += 1 progress = float(count) / total_docs * 100 current_task.update_state( state='PROGRESS', meta={'progress': progress}) post_batch_review.send(sender=do_batch_import, user_id=user_id) # Send success and failure notifications if len(ok) > 0: ok_message = ugettext('The review started for the following documents:') ok_list = '</li><li>'.join('<a href="%s">%s</a>' % (doc.get_absolute_url(), doc) for doc in ok) notify(user_id, '{} <ul><li>{}</li></ul>'.format( ok_message, ok_list )) if len(nok) > 0: nok_message = ugettext("We failed to start the review for the following documents:") nok_list = '</li><li>'.join('<a href="%s">%s</a>' % (doc.get_absolute_url(), doc) for doc in nok) notify(user_id, '{} <ul><li>{}</li></ul>'.format( nok_message, nok_list )) return 'done'
def batch_close_reviews(user_id, review_ids): """Close several reviews at once. Only reviewers can do this. """ logger.info('Closing several reviews at once: {}'.format( ', '.join(review_ids))) ok = [] nok = [] nb_reviews = len(review_ids) reviews = Review.objects \ .filter(reviewer_id=user_id) \ .filter(role=Review.ROLES.reviewer) \ .filter(status=Review.STATUSES.progress) \ .filter(id__in=review_ids) \ .select_related() counter = float(1) comments = None for review in reviews: # Update progress counter progress = counter / nb_reviews * 100 current_task.update_state( state='PROGRESS', meta={'progress': progress}) try: with transaction.atomic(): # Post an empty review logger.info('Closing review {}'.format(review.id)) review.post_review(comments, save=True) # Check if the review step has ended # TODO This is highly inefficient. Maybe one day # find another way to do it? document = review.document latest_revision = document.get_latest_revision() waiting_reviews = Review.objects \ .filter(document=document) \ .filter(revision=review.revision) \ .filter(role='reviewer') \ .exclude(closed_on=None) if waiting_reviews.count() == latest_revision.reviewers.count(): logger.info('Closing reviewers step') latest_revision.end_reviewers_step(save=False) user = User.objects.get(pk=user_id) activity_log.send(verb=Activity.VERB_CLOSED_REVIEWER_STEP, target=latest_revision, sender=do_batch_import, actor=user) ok.append(review.document) except: # noqa nok.append(review.document) pass counter += 1 if len(ok) > 0: ok_message = ugettext('You closed the review for the following documents:') ok_list = '</li><li>'.join('<a href="%s">%s</a>' % (doc.get_absolute_url(), doc) for doc in ok) notify(user_id, '{} <ul><li>{}</li></ul>'.format( ok_message, ok_list )) if len(nok) > 0: nok_message = ugettext("We failed to close the review for the following documents:") nok_list = '</li><li>'.join('<a href="%s">%s</a>' % (doc.get_absolute_url(), doc) for doc in nok) notify(user_id, '{} <ul><li>{}</li></ul>'.format( nok_message, nok_list )) return 'done'