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
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)
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
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}}
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
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
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)