def delete(self, entity):
    """Removes Ranker entry and all ReviewFollowers before deleting the entity.

    Args:
      entity: an existing entity in datastore
    """

    from soc.modules.gsoc.logic.models.review_follower import logic as \
        review_follower_logic

    # entries in the ranker can be removed by setting the score to None
    ranker = self.getRankerFor(entity)
    ranker.SetScore(entity.key().id_or_name(), None)

    # get all the ReviewFollwers that have this entity as it's scope
    fields = {'scope': entity}

    # TODO be sure that this captures all the followers
    followers = review_follower_logic.getForFields(fields)

    for follower in followers:
      review_follower_logic.delete(follower)

    # call to super to complete the deletion
    super(Logic, self).delete(entity)
    def delete(self, entity):
        """Removes Ranker entry and all ReviewFollowers before deleting the entity.

    Args:
      entity: an existing entity in datastore
    """

        from soc.modules.gsoc.logic.models.review_follower import logic as \
            review_follower_logic

        # entries in the ranker can be removed by setting the score to None
        ranker = self.getRankerFor(entity)
        ranker.SetScore(entity.key().id_or_name(), None)

        # get all the ReviewFollwers that have this entity as it's scope
        fields = {'scope': entity}

        # TODO be sure that this captures all the followers
        followers = review_follower_logic.getForFields(fields)

        for follower in followers:
            review_follower_logic.delete(follower)

        # call to super to complete the deletion
        super(Logic, self).delete(entity)
    def _createReviewFor(self, entity, comment, score=0, is_public=True):
        """Creates a review for the given proposal and sends 
       out a message to all followers.

    Args:
      entity: Student Proposal entity for which the review should be created
      comment: The textual contents of the review
      score: The score of the review (only used if the review is not public)
      is_public: Determines if the review is a public review
    """

        from soc.logic.helper import notifications as notifications_helper
        from soc.modules.gsoc.logic.models.review import logic as review_logic
        from soc.modules.gsoc.logic.models.review_follower import logic as \
            review_follower_logic

        # create the fields for the review entity
        fields = {
            'link_id': 't%i' % (int(time.time() * 100)),
            'scope': entity,
            'scope_path': entity.key().id_or_name(),
            'author': user_logic.logic.getForCurrentAccount(),
            'content': comment,
            'is_public': is_public,
        }

        # add the given score if the review is not public
        if not is_public:
            fields['score'] = score

        # create a new Review
        key_name = review_logic.getKeyNameFromFields(fields)
        review_entity = review_logic.updateOrCreateFromKeyName(
            fields, key_name)

        # get all followers
        fields = {'scope': entity}

        if is_public:
            fields['subscribed_public'] = True
        else:
            fields['subscribed_private'] = True

        followers = review_follower_logic.getForFields(fields)

        if is_public:
            # redirect to public page
            redirect_url = redirects.getPublicRedirect(entity, self._params)
        else:
            # redirect to review page
            redirect_url = redirects.getReviewRedirect(entity, self._params)

        for follower in followers:
            # sent to every follower except the reviewer
            if follower.user.key() != review_entity.author.key():
                notifications_helper.sendNewReviewNotification(
                    follower.user, review_entity, entity.title, redirect_url)
    def updatePublicContext(self, context, entity, params):
        """Updates the context for the public page with information from the entity.

    Args:
      context: the context that should be updated
      entity: a student proposal_entity used to set context
      params: dict with params for the view using this context
    """

        from soc.modules.gsoc.logic.models.review import logic as review_logic
        from soc.modules.gsoc.logic.models.review_follower import logic as \
            review_follower_logic

        student_entity = entity.scope

        context['student'] = student_entity
        context['student_name'] = student_entity.name()

        user_entity = user_logic.logic.getForCurrentAccount()

        # check if the current user is the student
        # pylint: disable-msg=E1103
        if user_entity.key() == student_entity.user.key():
            # show the proposal edit link
            context['edit_link'] = redirects.getEditRedirect(entity, params)

        # check if the current user is subscribed to this proposal's public reviews
        fields = {
            'user': user_entity,
            'scope': entity,
            'subscribed_public': True
        }

        context['is_subscribed'] = review_follower_logic.getForFields(
            fields, unique=True)

        context['public_reviews'] = review_logic.getReviewsForEntity(
            entity, is_public=True, order=['created'])
  def _getDefaultReviewContext(self, entity, org_admin,
                               mentor):
    """Returns the default context for the review page.

    Args:
      entity: Student Proposal entity
      org_admin: org admin entity for the current user/proposal (iff available)
      mentor: mentor entity for the current user/proposal (iff available)
    """

    from soc.modules.gsoc.logic.models.proposal_duplicates import logic \
        as duplicates_logic
    from soc.modules.gsoc.logic.models.review_follower import logic as \
        review_follower_logic

    context = {}

    context['student'] = entity.scope
    context['student_name'] = entity.scope.name()

    if entity.mentor:
      context['mentor_name'] = entity.mentor.name()
    else:
      context['mentor_name'] = "No mentor assigned"

    # set the possible mentors in the context
    possible_mentors = entity.possible_mentors

    if not possible_mentors:
      context['possible_mentors'] = "None"
    else:
      mentor_names = []

      for mentor_key in possible_mentors:
        possible_mentor = mentor_logic.logic.getFromKeyName(
            mentor_key.id_or_name())
        mentor_names.append(possible_mentor.name())

      context['possible_mentors'] = ', '.join(mentor_names)

    # update the reviews context
    self._updateReviewsContext(context, entity)

    # update the scores context
    self._updateScoresContext(context, entity)

    if mentor:
      context['is_mentor'] = True
      if not entity.mentor or entity.mentor.key() != mentor.key():
        # which button to (un)propose yourself as mentor should we show
        if mentor.key() in possible_mentors:
          # show "No longer willing to mentor"
          context['remove_me_as_mentor'] = True
        else:
          # show "I am willing to mentor"
          context['add_me_as_mentor'] = True

    if org_admin:
      context['is_org_admin'] = True

      # when the duplicates can be visible obtain the
      # duplicates for this proposal
      if entity.program.duplicates_visible:
        fields = {'student': entity.scope,
                      'is_duplicate': True}

        duplicate_entity = duplicates_logic.getForFields(fields, unique=True)

        if duplicate_entity:
          # this list also contains the current proposal
          # entity, so remove it
          duplicate_keys = duplicate_entity.duplicates
          duplicate_keys.remove(entity.key())
          context['sp_duplicates'] = db.get(duplicate_keys)

    user_entity = user_logic.logic.getCurrentUser()

    # check if the current user is subscribed to public or private reviews
    fields = {'scope': entity,
              'user': user_entity,}
    follower_entity = review_follower_logic.getForFields(fields, unique=True)

    if follower_entity:
      # pylint: disable=E1103
      context['is_subscribed'] =  follower_entity.subscribed_public

    return context
  def createReviewFor(self, view, entity, user, comment, score=0, is_public=True):
    """Creates a review of the user for the given proposal and sends 
       out a message to all followers.

    Args:
      view: student proposal view
      entity: Student Proposal entity for which the review should be created
      user: the user who is leaving the review
      comment: The textual contents of the review
      score: The score of the review (only used if the review is not public)
      is_public: Determines if the review is a public review
    """

    from soc.logic.helper import notifications as notifications_helper
    from soc.views.helper import redirects
    from soc.modules.gsoc.logic.models.review import logic as review_logic
    from soc.modules.gsoc.logic.models.review_follower import logic as \
        review_follower_logic

    # create the fields for the review entity
    fields = {'link_id': 't%i' % (int(time.time()*100)),
        'scope': entity,
        'scope_path': entity.key().id_or_name(),
        'author': user,
        'content': comment if comment else '',
        'is_public': is_public,
        }

    # add the given score if the review is not public
    if not is_public:
      fields['score'] = score

    # create a new Review
    key_name = review_logic.getKeyNameFromFields(fields)
    review_entity = review_logic.updateOrCreateFromKeyName(fields, key_name)

    # get all followers
    fields = {'scope': entity}

    if is_public:
      fields['subscribed_public'] = True
    else:
      fields['subscribed_private'] = True

    followers = review_follower_logic.getForFields(fields)

    # retrieve the redirects for the student and one for the org members
    private_redirect_url = redirects.getStudentPrivateRedirect(entity,
                                                               view._params)
    review_redirect_url = redirects.getReviewRedirect(entity, view._params)

    student_id = entity.scope.link_id

    for follower in followers:
      # sent to every follower except the reviewer
      if follower.user.key() != review_entity.author.key():
        if follower.user.link_id == student_id:
          redirect_url = private_redirect_url
        else:
          redirect_url = review_redirect_url

        notifications_helper.sendNewReviewNotification(follower.user,
            review_entity, entity.title, redirect_url)
    def _getDefaultReviewContext(self, entity, org_admin, mentor):
        """Returns the default context for the review page.

    Args:
      entity: Student Proposal entity
      org_admin: org admin entity for the current user/proposal (iff available)
      mentor: mentor entity for the current user/proposal (iff available)
    """

        from soc.modules.gsoc.logic.models.review import logic as review_logic
        from soc.modules.gsoc.logic.models.review_follower import logic as \
            review_follower_logic

        context = {}

        context['student'] = entity.scope
        context['student_name'] = entity.scope.name()

        if entity.mentor:
            context['mentor_name'] = entity.mentor.name()
        else:
            context['mentor_name'] = "No mentor assigned"

        # set the possible mentors in the context
        possible_mentors = entity.possible_mentors

        if not possible_mentors:
            context['possible_mentors'] = "None"
        else:
            mentor_names = []

            for mentor_key in possible_mentors:
                possible_mentor = mentor_logic.logic.getFromKeyName(
                    mentor_key.id_or_name())
                mentor_names.append(possible_mentor.name())

            context['possible_mentors'] = ', '.join(mentor_names)

        # order the reviews by ascending creation date
        order = ['created']

        # get the public reviews
        public_reviews = review_logic.getReviewsForEntity(entity,
                                                          is_public=True,
                                                          order=order)

        # get the private reviews
        private_reviews = review_logic.getReviewsForEntity(entity,
                                                           is_public=False,
                                                           order=order)

        # store the reviews in the context
        context['public_reviews'] = public_reviews
        context['private_reviews'] = private_reviews

        # create a summary of all the private reviews
        review_summary = {}

        for private_review in private_reviews:

            if private_review.score == 0:
                continue

            reviewer = private_review.author

            reviewer_key = reviewer.key().id_or_name()
            reviewer_summary = review_summary.get(reviewer_key)

            if reviewer_summary:
                # we already have something on file for this reviewer
                old_total_score = reviewer_summary['total_score']
                reviewer_summary[
                    'total_score'] = old_total_score + private_review.score
                reviewer_summary['individual_scores'].append(
                    private_review.score)

                old_total_comments = reviewer_summary['total_comments']
                reviewer_summary['total_comments'] = old_total_comments + 1
            else:
                review_summary[reviewer_key] = {
                    'name': reviewer.name,
                    'total_comments': 1,
                    'total_score': private_review.score,
                    'individual_scores': [private_review.score]
                }

        context['review_summary'] = review_summary

        # fill a score summary
        score_summary = []
        total_scores = [i['total_score'] for i in review_summary.itervalues()]
        max_score = max(total_scores) if total_scores else 0
        min_score = min(total_scores) if total_scores else 0
        for score in xrange(min_score, max_score + 1):
            number = len([summary for summary in review_summary.itervalues() \
                if summary['total_score'] == score])
            if number:
                score_summary.append({'score': score, 'number': number})
        context['score_summary'] = score_summary

        # which button should we show to the mentor?
        if mentor:
            context['is_mentor'] = True
            if mentor.key() in possible_mentors:
                # show "No longer willing to mentor"
                context['remove_me_as_mentor'] = True
            else:
                # show "I am willing to mentor"
                context['add_me_as_mentor'] = True

        if org_admin:
            context['is_org_admin'] = True

        user_entity = user_logic.logic.getForCurrentAccount()

        # check if the current user is subscribed to public or private reviews
        fields = {
            'scope': entity,
            'user': user_entity,
        }
        follower_entity = review_follower_logic.getForFields(fields,
                                                             unique=True)

        if follower_entity:
            # pylint: disable-msg=E1103
            context['is_subscribed_public'] = follower_entity.subscribed_public
            context[
                'is_subscribed_private'] = follower_entity.subscribed_private

        return context
    def createReviewFor(self,
                        view,
                        entity,
                        user,
                        comment,
                        score=0,
                        is_public=True):
        """Creates a review of the user for the given proposal and sends 
       out a message to all followers.

    Args:
      view: student proposal view
      entity: Student Proposal entity for which the review should be created
      user: the user who is leaving the review
      comment: The textual contents of the review
      score: The score of the review (only used if the review is not public)
      is_public: Determines if the review is a public review
    """

        from soc.logic.helper import notifications as notifications_helper
        from soc.views.helper import redirects
        from soc.modules.gsoc.logic.models.review import logic as review_logic
        from soc.modules.gsoc.logic.models.review_follower import logic as \
            review_follower_logic

        # create the fields for the review entity
        fields = {
            'link_id': 't%i' % (int(time.time() * 100)),
            'scope': entity,
            'scope_path': entity.key().id_or_name(),
            'author': user,
            'content': comment if comment else '',
            'is_public': is_public,
        }

        # add the given score if the review is not public
        if not is_public:
            fields['score'] = score

        # create a new Review
        key_name = review_logic.getKeyNameFromFields(fields)
        review_entity = review_logic.updateOrCreateFromKeyName(
            fields, key_name)

        # get all followers
        fields = {'scope': entity}

        if is_public:
            fields['subscribed_public'] = True
        else:
            fields['subscribed_private'] = True

        followers = review_follower_logic.getForFields(fields)

        # retrieve the redirects for the student and one for the org members
        private_redirect_url = redirects.getStudentPrivateRedirect(
            entity, view._params)
        review_redirect_url = redirects.getReviewRedirect(entity, view._params)

        student_id = entity.scope.link_id

        for follower in followers:
            # sent to every follower except the reviewer
            if follower.user.key() != review_entity.author.key():
                if follower.user.link_id == student_id:
                    redirect_url = private_redirect_url
                else:
                    redirect_url = review_redirect_url

                notifications_helper.sendNewReviewNotification(
                    follower.user, review_entity, entity.title, redirect_url)