def testCalculateFinishedThroughPostWithCorrectXsrfToken(self):
    """Tests the result after calculating duplicate proposals is finished.

    Through HTTP POST with correct XSRF token, when finished
    (there is no org to calculate), all pb records with no duplicate proposals
    are deleted and there is no taskqueue spawned.
    """
    pd_fields  = {
        'program': self.program,
        'student': self.student,
        'orgs':[self.organization.key()],
        'duplicates': [self.student_proposal.key()],
        'is_duplicate': False
        }
    pd_logic.updateOrCreateFromFields(pd_fields)
    pds = pd_logic.getForFields({'program': self.program})
    self.assertEqual(len(pds), 1)
    fields = {'scope': self.program,
              'slots >': 0,
              'status': 'active'}
    # Get all organizations and save the cursor
    q = gsoc_organization_logic.getQueryForFields(fields)
    q.fetch(3)
    org_cursor = q.cursor()
    url = '/tasks/gsoc/proposal_duplicates/calculate'
    postdata = {'program_key': self.program.key().name(),
        'org_cursor': unicode(org_cursor)}
    xsrf_token = self.getXsrfToken(url, data=postdata)
    postdata.update(xsrf_token=xsrf_token)
    response = self.client.post(url, postdata)
    self.assertEqual(response.status_code, httplib.OK)
    pds = pd_logic.getForFields({'program': self.program})
    self.assertEqual(len(pds), 0)
    task_url = '/tasks/gsoc/proposal_duplicates/calculate'
    self.assertTasksInQueue(n=0, url=task_url)
Example #2
0
    def testCalculateFinishedThroughPostWithCorrectXsrfToken(self):
        """Tests the result after calculating duplicate proposals is finished.

    Through HTTP POST with correct XSRF token, when finished
    (there is no org to calculate), all pb records with no duplicate proposals
    are deleted and there is no taskqueue spawned.
    """
        pd_fields = {
            'program': self.program,
            'student': self.student,
            'orgs': [self.organization.key()],
            'duplicates': [self.student_proposal.key()],
            'is_duplicate': False
        }
        pd_logic.updateOrCreateFromFields(pd_fields)
        pds = pd_logic.getForFields({'program': self.program})
        self.assertEqual(len(pds), 1)
        fields = {'scope': self.program, 'slots >': 0, 'status': 'active'}
        # Get all organizations and save the cursor
        q = gsoc_organization_logic.getQueryForFields(fields)
        q.fetch(3)
        org_cursor = q.cursor()
        url = '/tasks/gsoc/proposal_duplicates/calculate'
        postdata = {
            'program_key': self.program.key().name(),
            'org_cursor': unicode(org_cursor)
        }
        xsrf_token = self.getXsrfToken(url, data=postdata)
        postdata.update(xsrf_token=xsrf_token)
        response = self.client.post(url, postdata)
        self.assertEqual(response.status_code, httplib.OK)
        pds = pd_logic.getForFields({'program': self.program})
        self.assertEqual(len(pds), 0)
        task_url = '/tasks/gsoc/proposal_duplicates/calculate'
        self.assertTasksInQueue(n=0, url=task_url)
def calculate(request, *args, **kwargs):
    """Calculates the duplicate proposals in a given program for
  a student on a per Organization basis.

  Expects the following to be present in the POST dict:
    program_key: Specifies the program key name for which to find the
                 duplicate proposals
    org_cursor: Specifies the organization datastore cursor from which to
                start the processing of finding the duplicate proposals

  Args:
    request: Django Request object
  """

    from soc.modules.gsoc.logic.models.student_proposal import logic \
        as sp_logic

    post_dict = request.POST

    program_key = post_dict.get('program_key')
    if not program_key:
        # invalid task data, log and return OK
        return error_handler.logErrorAndReturnOK('Invalid program key: %s' %
                                                 post_dict)

    program_entity = program_logic.getFromKeyName(program_key)
    if not program_entity:
        # invalid program specified, log and return OK
        return error_handler.logErrorAndReturnOK(
            'Invalid program specified: %s' % program_key)

    fields = {'scope': program_entity, 'slots >': 0, 'status': 'active'}

    # get the organization and update the cursor if possible
    q = org_logic.getQueryForFields(fields)

    # retrieve the org_cursor from POST data
    org_cursor = post_dict.get('org_cursor')

    if org_cursor:
        org_cursor = str(org_cursor)
        q.with_cursor(org_cursor)

    result = q.fetch(1)
    # update the cursor
    org_cursor = q.cursor()

    if result:
        org_entity = result[0]

        # get all the proposals likely to be accepted in the program
        accepted_proposals = sp_logic.getProposalsToBeAcceptedForOrg(
            org_entity)

        for ap in accepted_proposals:
            student_entity = ap.scope
            proposal_duplicate = pd_logic.getForFields(
                {'student': student_entity}, unique=True)
            if proposal_duplicate and ap.key(
            ) not in proposal_duplicate.duplicates:
                # non-counted (to-be) accepted proposal found
                pd_fields = {
                    'duplicates': proposal_duplicate.duplicates + [ap.key()],
                }
                pd_fields['is_duplicate'] = len(pd_fields['duplicates']) >= 2
                if org_entity.key() not in proposal_duplicate.orgs:
                    pd_fields['orgs'] = proposal_duplicate.orgs + [
                        org_entity.key()
                    ]

                proposal_duplicate = pd_logic.updateEntityProperties(
                    proposal_duplicate, pd_fields)
            else:
                pd_fields = {
                    'program': program_entity,
                    'student': student_entity,
                    'orgs': [org_entity.key()],
                    'duplicates': [ap.key()],
                    'is_duplicate': False
                }
                proposal_duplicate = pd_logic.updateOrCreateFromFields(
                    pd_fields)

        # Adds a new task that performs duplicate calculation for
        # the next organization.
        task_params = {
            'program_key': program_key,
            'org_cursor': unicode(org_cursor)
        }
        task_url = '/tasks/gsoc/proposal_duplicates/calculate'

        new_task = taskqueue.Task(params=task_params, url=task_url)
        new_task.add()
    else:
        # There aren't any more organizations to process. So delete
        # all the proposals for which there are not more than one
        # proposal for duplicates property.
        pd_logic.deleteAllForProgram(program_entity, non_dupes_only=True)

        # update the proposal duplicate status and its timestamp
        pds_entity = pds_logic.getOrCreateForProgram(program_entity)
        new_fields = {
            'status': 'idle',
            'calculated_on': datetime.datetime.now()
        }
        pds_logic.updateEntityProperties(pds_entity, new_fields)

    # return OK
    return http.HttpResponse()
def calculate(request, *args, **kwargs):
  """Calculates the duplicate proposals in a given program for
  a student on a per Organization basis.

  Expects the following to be present in the POST dict:
    program_key: Specifies the program key name for which to find the
                 duplicate proposals
    org_cursor: Specifies the organization datastore cursor from which to
                start the processing of finding the duplicate proposals

  Args:
    request: Django Request object
  """

  from soc.modules.gsoc.logic.models.student_proposal import logic \
      as sp_logic

  post_dict = request.POST

  program_key = post_dict.get('program_key')
  if not program_key:
    # invalid task data, log and return OK
    return error_handler.logErrorAndReturnOK(
        'Invalid program key: %s' % post_dict)

  program_entity = program_logic.getFromKeyName(program_key)
  if not program_entity:
    # invalid program specified, log and return OK
    return error_handler.logErrorAndReturnOK(
        'Invalid program specified: %s' % program_key)

  fields = {'scope': program_entity,
            'slots >': 0,
            'status': 'active'}

  # get the organization and update the cursor if possible
  q = org_logic.getQueryForFields(fields)

  # retrieve the org_cursor from POST data
  org_cursor = post_dict.get('org_cursor')

  if org_cursor:
    org_cursor = str(org_cursor)
    q.with_cursor(org_cursor)

  result = q.fetch(1)
  # update the cursor
  org_cursor = q.cursor()

  if result:
    org_entity = result[0]

    # get all the proposals likely to be accepted in the program
    accepted_proposals = sp_logic.getProposalsToBeAcceptedForOrg(org_entity)

    for ap in accepted_proposals:
      student_entity = ap.scope
      proposal_duplicate = pd_logic.getForFields({'student': student_entity},
                                                 unique=True)
      if proposal_duplicate and ap.key() not in proposal_duplicate.duplicates:
        # non-counted (to-be) accepted proposal found
        pd_fields = {
            'duplicates': proposal_duplicate.duplicates + [ap.key()],
            }
        pd_fields['is_duplicate'] = len(pd_fields['duplicates']) >= 2
        if org_entity.key() not in proposal_duplicate.orgs:
          pd_fields['orgs'] = proposal_duplicate.orgs + [org_entity.key()]

        proposal_duplicate = pd_logic.updateEntityProperties(
            proposal_duplicate, pd_fields)
      else:
        pd_fields  = {
            'program': program_entity,
            'student': student_entity,
            'orgs':[org_entity.key()],
            'duplicates': [ap.key()],
            'is_duplicate': False
            }
        proposal_duplicate = pd_logic.updateOrCreateFromFields(pd_fields)

    # Adds a new task that performs duplicate calculation for
    # the next organization.
    task_params = {'program_key': program_key,
                   'org_cursor': unicode(org_cursor)}
    task_url = '/tasks/gsoc/proposal_duplicates/calculate'

    new_task = taskqueue.Task(params=task_params, url=task_url)
    new_task.add()
  else:
    # There aren't any more organizations to process. So delete
    # all the proposals for which there are not more than one
    # proposal for duplicates property.
    pd_logic.deleteAllForProgram(program_entity, non_dupes_only=True)

    # update the proposal duplicate status and its timestamp
    pds_entity = pds_logic.getOrCreateForProgram(program_entity)
    new_fields = {'status': 'idle',
                  'calculated_on': datetime.datetime.now()}
    pds_logic.updateEntityProperties(pds_entity, new_fields)

  # return OK
  return http.HttpResponse()