예제 #1
0
def get_candidates_of_talent_pool(talent_pool,
                                  oauth_token=None,
                                  request_params=None):
    """
    Fetch all candidates of a talent-pool
    :param talent_pool: TalentPool Object
    :param oauth_token: Authorization Token
    :param request_params: Request parameters
    :return: A dict containing info of all candidates according to query parameters
    """
    if request_params is None:
        request_params = dict()
    else:
        request_params['talent_pool_id'] = talent_pool.id

    request_params = dict((k, v) for k, v in request_params.iteritems() if v)

    # Query Candidate Search API to get all candidates of a given talent-pipeline
    is_successful, response = get_candidates_from_search_api(
        request_params, generate_jwt_header(oauth_token, talent_pool.user_id))

    if not is_successful:
        raise NotFoundError(
            "Couldn't get candidates from candidates search service because: %s"
            % response)
    else:
        return response
예제 #2
0
    def get(self, **kwargs):
        """
        Use this endpoint to retrieve all candidates present in list (smart or dumb list)
        Input:
            URL Arguments `smartlist_id` (Required): id of smartlist
            Accepts (query string parameters):
                fields :: comma separated values
                sort_by ::  Sort by field
                limit :: Size of each page
                page :: Page number or cursor string
        :return : List of candidates present in list (smart list or dumb list)
        :rtype: json
        """
        smartlist_id = kwargs.get('smartlist_id')
        smartlist = Smartlist.query.get(smartlist_id)
        if not smartlist or smartlist.is_hidden:
            raise NotFoundError("List id does not exists.")

        # check whether smartlist belongs to user's domain
        if request.user.role.name != 'TALENT_ADMIN' and smartlist.user.domain_id != request.user.domain_id:
            raise ForbiddenError(
                "Provided list does not belong to user's domain")

        request_params = dict()
        request_params['facets'] = request.args.get('facets', '')
        request_params['fields'] = request.args.get('fields', '')
        request_params['sort_by'] = request.args.get('sort_by', '')
        request_params['limit'] = request.args.get('limit', '')
        request_params['page'] = request.args.get('page', '')

        return get_smartlist_candidates(smartlist, request.oauth_token,
                                        request_params)
예제 #3
0
def get_candidates_of_talent_pipeline(talent_pipeline,
                                      oauth_token=None,
                                      request_params=None):
    """
    Fetch all candidates of a talent-pipeline
    :param talent_pipeline: TalentPipeline Object
    :param oauth_token: Authorization Token
    :param request_params: Request parameters
    :return: A dict containing info of all candidates according to query parameters
    """

    if request_params is None:
        request_params = dict()

    try:
        if talent_pipeline.search_params:
            request_params.update(json.loads(talent_pipeline.search_params))

    except Exception as e:
        raise InvalidUsage(
            error_message=
            "Search params of talent pipeline or its smartlists are in bad format "
            "because: %s" % e.message)

    request_params['talent_pool_id'] = talent_pipeline.talent_pool_id

    request_params = dict((k, v) for k, v in request_params.iteritems() if v)

    request_params['talent_pipelines'] = str(talent_pipeline.id)

    # Query Candidate Search API to get all candidates of a given talent-pipeline
    is_successful, response = get_candidates_from_search_api(
        request_params,
        generate_jwt_header(oauth_token, talent_pipeline.user_id))

    if not is_successful:
        raise NotFoundError(
            "Couldn't get candidates from candidates search service because: %s"
            % response)
    else:
        return response
예제 #4
0
    def delete(self, **kwargs):
        """
        Deletes (hides) the smartlist

        :return: Id of deleted smartlist.
        """
        list_id = kwargs.get('id')
        if not list_id:
            return InvalidUsage("List id is required for deleting a list")

        smartlist = Smartlist.query.get(list_id)
        if not smartlist or smartlist.is_hidden:
            raise NotFoundError("List id does not exists")

        if request.user.role.name == 'USER' and smartlist.user.id != request.user.id:
            raise ForbiddenError(
                "Logged-in user doesn't have appropriate permissions to delete this smartlist"
            )

        # check whether smartlist belongs to user's domain
        if request.user.role.name != 'TALENT_ADMIN' and smartlist.user.domain_id != request.user.domain_id:
            raise ForbiddenError(
                "Logged-in user doesn't have appropriate permissions to delete this smartlist"
            )

        smartlist_candidate_ids = SmartlistCandidate.query.with_entities(
            SmartlistCandidate.candidate_id).filter(
                SmartlistCandidate.smartlist_id == list_id).all()
        smartlist_candidate_ids = [
            smartlist_candidate_id[0]
            for smartlist_candidate_id in smartlist_candidate_ids
        ]
        smartlist.delete()
        if smartlist_candidate_ids:
            logger.info(
                "Candidates %s of SmartList %s are going to be updated in Amazon Cloud "
                "Search" % (smartlist_candidate_ids, list_id))
            update_candidates_on_cloudsearch(request.oauth_token,
                                             smartlist_candidate_ids)
        return {'smartlist': {'id': smartlist.id}}
예제 #5
0
def get_smartlist_candidates(smartlist, oauth_token=None, request_params=None):
    """
    This endpoint will be used to get smartlist candidates for given duration
    :param search_params: search parameters dict
    :param oauth_token: OAuth Token value
    :return:
    """
    if request_params is None:
        request_params = dict()
    if smartlist.talent_pipeline:
        if smartlist.talent_pipeline.search_params:
            try:
                request_params.update(
                    json.loads(smartlist.talent_pipeline.search_params))
            except Exception as e:
                raise InvalidUsage(
                    "Search params of talent pipeline are in bad format because: %s"
                    % e.message)

        request_params[
            'talent_pool_id'] = smartlist.talent_pipeline.talent_pool_id
        request_params['talent_pipelines'] = str(smartlist.talent_pipeline.id)

    if smartlist.search_params:
        request_params['smartlist_ids'] = smartlist.id
    else:
        request_params['dumb_list_ids'] = smartlist.id

    request_params = dict((k, v) for k, v in request_params.iteritems() if v)

    is_successful, response = get_candidates_from_search_api(
        request_params, generate_jwt_header(oauth_token, smartlist.user_id))
    if not is_successful:
        raise NotFoundError("Couldn't get candidates for smartlist %s" %
                            smartlist.id)
    else:
        return response
예제 #6
0
def get_stats_generic_function(container_object,
                               container_name,
                               user=None,
                               from_date_string='',
                               to_date_string='',
                               interval=1,
                               is_update=False,
                               offset=0):
    """
    This method will be used to get stats for talent-pools, talent-pipelines or smartlists.
    :param container_object: TalentPipeline, TalentPool or SmartList Object
    :param container_name:
    :param user: Logged-in user
    :param from_date_string: From Date String (In Client's Local TimeZone)
    :param to_date_string: To Date String (In Client's Local TimeZone)
    :param interval: Interval in days
    :param is_update: Either stats update process is in progress
    :param offset: Timezone offset from utc i.e. if client's lagging 4 hours behind utc, offset value should be -4
    :return:
    """
    if not container_object:
        raise NotFoundError("%s doesn't exist in database" % container_name)

    if user and container_object.user.domain_id != user.domain_id:
        raise ForbiddenError(
            "Logged-in user %s is unauthorized to get stats of %s: %s" %
            (user.id, container_name, container_object.id))

    if not is_number(offset) or math.ceil(abs(float(offset))) > 12:
        raise InvalidUsage(
            "Value of offset should be an integer and less than or equal to 12"
        )

    offset = int(math.ceil(float(offset)))

    current_date_time = datetime.utcnow()

    ninety_days_old_date_time = current_date_time - timedelta(days=90)

    try:
        # To convert UTC time to any other time zone we can use `offset_date_time` with inverted value of offset
        from_date = parse(from_date_string).replace(tzinfo=None) if from_date_string \
            else offset_date_time(ninety_days_old_date_time, -1 * offset)
        to_date = parse(to_date_string).replace(tzinfo=None) if to_date_string else \
            offset_date_time(current_date_time, -1 * offset)
    except Exception as e:
        raise InvalidUsage(
            "Either 'from_date' or 'to_date' is invalid because: %s" %
            e.message)

    if offset_date_time(from_date, offset) < container_object.added_time:
        from_date = offset_date_time(container_object.added_time, -1 * offset)

    if offset_date_time(from_date, offset) < ninety_days_old_date_time:
        raise InvalidUsage(
            "`Stats data older than 90 days cannot be retrieved`")

    if from_date > to_date:
        raise InvalidUsage("`to_date` cannot come before `from_date`")

    if offset_date_time(to_date, offset) > current_date_time:
        raise InvalidUsage("`to_date` cannot be in future")

    if not is_number(interval):
        raise InvalidUsage("Interval '%s' should be integer" % interval)

    interval = int(interval)
    if interval < 1:
        raise InvalidUsage(
            "Interval's value should be greater than or equal to 1 day")

    if container_name == 'TalentPipeline':
        get_stats_for_given_day = get_talent_pipeline_stat_for_given_day
    elif container_name == 'TalentPool':
        get_stats_for_given_day = get_talent_pool_stat_for_a_given_day
    elif container_name == 'SmartList':
        get_stats_for_given_day = get_smartlist_stat_for_a_given_day
    else:
        raise Exception("Container %s is not supported for this method" %
                        container_name)

    list_of_stats_dicts = []

    to_date = to_date.replace(hour=23, minute=59, second=59)
    from_date = from_date.replace(hour=23, minute=59, second=59)

    if is_update:
        to_date -= timedelta(days=interval)

    while to_date.date() >= from_date.date():
        list_of_stats_dicts.append({
            'total_number_of_candidates':
            get_stats_for_given_day(container_object,
                                    offset_date_time(to_date, offset)),
            'added_datetime':
            to_date.date().isoformat(),
        })
        to_date -= timedelta(days=interval)

    reference_stat = get_stats_for_given_day(container_object,
                                             offset_date_time(to_date, offset))
    for index, stat_dict in enumerate(list_of_stats_dicts):
        stat_dict['number_of_candidates_added'] = stat_dict[
            'total_number_of_candidates'] - (
                list_of_stats_dicts[index + 1]['total_number_of_candidates']
                if index + 1 < len(list_of_stats_dicts) else reference_stat)

    return list_of_stats_dicts
예제 #7
0
    def get(self, **kwargs):
        """Retrieve list information
        List must belong to auth user's domain
        Call this resource from url:
            /v1/smartlists?page=1&page_size=10 :: to retrieve all the smartlists in user's domain
            /v1/smartlists/<int:id> :: to get single smartlist

        example: http://localhost:8008/v1/smartlists/2
        Returns: List in following json format
            {
              "smartlist": {
                "total_found": 3,
                "user_id": 1,
                "id": 1,
                "name": "my list"
                "search_params": {"location": "San Jose, CA"}
              }
            }
        """
        list_id = kwargs.get('id')
        candidate_count = request.args.get('candidate-count', False)

        if not is_number(candidate_count) or int(candidate_count) not in (
                True, False):
            raise InvalidUsage("`candidate_count` field value can be 0 or 1")

        auth_user = request.user
        if list_id:
            smartlist = Smartlist.query.get(list_id)
            if not smartlist or smartlist.is_hidden:
                raise NotFoundError("List id does not exists")
            # check whether smartlist belongs to user's domain
            if request.user.role.name != 'TALENT_ADMIN' and smartlist.user.domain_id != auth_user.domain_id:
                raise ForbiddenError("List does not belong to user's domain")
            return {
                'smartlist':
                create_smartlist_dict(smartlist, request.oauth_token,
                                      int(candidate_count))
            }
        else:
            # Return all smartlists from user's domain
            page = request.args.get('page', DEFAULT_PAGE)
            per_page = request.args.get('per_page', DEFAULT_PAGE_SIZE)
            total_number_of_smartlists = Smartlist.query.join(
                Smartlist.user).filter(User.domain_id == auth_user.domain_id,
                                       Smartlist.is_hidden == 0).count()

            if not is_number(page) or not is_number(
                    per_page) or int(page) < 1 or int(per_page) < 1:
                raise InvalidUsage(
                    "page and per_page should be positive integers")

            page = int(page)
            per_page = int(per_page)

            headers = generate_pagination_headers(total_number_of_smartlists,
                                                  per_page, page)

            response = {
                'smartlists':
                get_all_smartlists(auth_user, request.oauth_token, int(page),
                                   int(per_page), candidate_count),
                'page_number':
                page,
                'smartlists_per_page':
                per_page,
                'total_number_of_smartlists':
                total_number_of_smartlists
            }
            return ApiResponse(response=response, headers=headers, status=200)