def _add_or_update_preferred_locations(preferred_locations, is_updating, user_id, candidate_id, existing_data): # Remove duplicates preferred_locations = remove_duplicates(preferred_locations) # Aggregate formatted & validated preferred locations' data validated_preferred_locations_data = [] for index, preferred_location in enumerate(preferred_locations): preferred_location_dict = dict( iso3166_country=clean( preferred_location.get('iso3166_country')).upper(), iso3166_subdivision=clean( preferred_location.get('iso3166_subdivision')).upper(), state=clean(preferred_location.get('state')), city=clean(preferred_location.get('city')), zip_code=sanitize_zip_code(preferred_location.get('zip_code'))) # Remove empty data preferred_location_dict = purge_dict(preferred_location_dict, strip=False) # Prevent adding empty records if not preferred_location_dict: continue validated_preferred_locations_data.append(preferred_location_dict) return validated_preferred_locations_data
def _add_or_update_work_preferences(work_preferences, is_updating, user_id, candidate_id, existing_data): # Remove duplicates work_preferences = remove_duplicates(work_preferences) # Aggregated formatted & validated work preferences' data validated_work_preferences = [] for index, preference in enumerate(work_preferences): preference_dict = dict( relocate=preference.get('relocate'), authorization=preference.get('authorization'), telecommute=preference.get('telecommute'), travel_percentage=preference.get('travel_percentage'), hourly_rate=str(preference['hourly_rate']) if preference.get('hourly_rate') else None, salary=preference.get('salary'), tax_terms=preference.get('tax_terms'), third_party=preference.get('third_party'), security_clearance=preference.get('security_clearance'), employment_type=preference.get('employment_type')) # Remove empty data preference_dict = purge_dict(preference_dict) validated_work_preferences.append(preference_dict) return validated_work_preferences
def _add_or_update_military_services(military_services, is_updating, user_id, candidate_id, existing_data): # Remove duplicates military_services = remove_duplicates(military_services) # Aggregate formatted & validated military services' data validated_military_services_data = [] for index, service in enumerate(military_services): service_dict = dict(iso3166_country=(service.get('iso3166_country') or '').upper(), service_status=service.get('status'), highest_rank=service.get('highest_rank'), highest_grade=service.get('highest_grade'), branch=service.get('branch'), comments=service.get('comments'), start_year=service.get('start_year'), start_month=service.get('start_month'), end_year=service.get('end_year'), end_month=service.get('end_month')) # Remove empty data service_dict = purge_dict(service_dict) # Prevent adding empty records if not service_dict: continue validated_military_services_data.append(service_dict) return validated_military_services_data
def _add_or_update_photos(photos, is_updating, user_id, candidate_id, existing_data): # Remove duplicates photos = remove_duplicates(photos) # Aggregate formatted & validated photos' data validated_photos_data = [] # Check if of candidate's photos has is_default set to true photo_has_default = any( [isinstance(photo.get('is_default'), bool) for photo in photos]) for index, photo in enumerate(photos): # If there is no default value, the first photo will be set as the default photo is_default = index == 0 if not photo_has_default else photo.get( 'is_default') photo_dict = dict(image_url=photo.get('image_url'), is_default=is_default) # Remove empty data photo_dict = purge_dict(photo_dict) # If photo is being added, image_url is required if not is_updating and not photo_dict.get('image_url'): raise InvalidUsage('Image url is required when adding candidate') validated_photos_data.append(photo_dict) return validated_photos_data
def _add_or_update_tags(tags, is_updating, user_id, candidate_id, existing_data): # Remove duplicate data tags = remove_duplicates(tags) # Aggregated formatted & validated tags' data validated_tags = [] for index, tag in enumerate(tags): tag_dict = dict(name=tag['name'].strip()) validated_tags.append(tag_dict) return validated_tags
def _add_or_update_addresses(addresses, user_id, is_updating, existing_data, candidate_id): """ - Duplicate dict(s) will be removed - The first address will be set as default if none of the addresses is set as the default address """ # Remove duplicates addresses = remove_duplicates(addresses) # Aggregate formatted & validated address data validated_addresses_data = [] # Check if any of the addresses is set as the default address addresses_have_default = [ isinstance(address.get('is_default'), bool) for address in addresses ] for index, address in enumerate(addresses): zip_code = sanitize_zip_code( address['zip_code']) if address.get('zip_code') else None city = (address.get('city') or '').strip() iso3166_subdivision = (address.get('iso3166_subdivision') or '').upper() address_dict = dict( address_line_1=address.get('address_line_1'), address_line_2=address.get('address_line_2'), zip_code=zip_code, state=address.get('state'), city=city, iso3166_subdivision=iso3166_subdivision, iso3166_country=(address.get('iso3166_country') or '').upper(), po_box=address.get('po_box'), is_default=index == 0 if not addresses_have_default else address.get('is_default'), coordinates=get_coordinates(zipcode=zip_code, city=city, state=iso3166_subdivision)) # Remove empty data from address dict address_dict = purge_dict(address_dict) # Prevent adding empty records if not address_dict: continue validated_addresses_data.append(address_dict) return validated_addresses_data
def _add_or_update_emails(emails, is_updating, user_id, existing_data, candidate_id): """ Function will normalize, validate, and return email objects for adding or updating candidate's emails If intend is to update, all changes will be tracked """ # Remove duplicates emails = remove_duplicates(emails) # Aggregate formatted & validated email data validated_emails_data = [] # Check if any of the emails is set as the default email emails_have_default = [ isinstance(email.get('is_default'), bool) for email in emails ] for i, email in enumerate(emails): # Normalize email address # Ensure email address is properly formatted # If email address is empty/null, process the next email object email_address = (email.get('address') or '').strip().lower() if email_address: if not is_valid_email(email_address): raise InvalidUsage(INVALID_EMAIL[0], INVALID_EMAIL[1]) elif not email_address: continue # Set email's label to 'Other' if it doesn't match any of the predefined email labels label = (email.get('label') or '').lower() if not label or label not in ('Primary', 'Home', 'Work', 'Other'): label = 'Primary' label = label.title() # First email will be set as default if no other email is set as default default = i == 0 if not any(emails_have_default) else email.get( 'is_default') email_dict = dict(label=label, address=email_address, is_default=default) validated_emails_data.append(email_dict) return validated_emails_data
def _add_or_update_social_networks(social_networks, is_updating, user_id, candidate_id, existing_data): # Remove duplicate data social_networks = remove_duplicates(social_networks) # Aggregate formatted & validated social networks' data checked_social_networks_data = [] for index, social_network in enumerate(social_networks): social_network_dict = dict( name=social_network['name'].strip(), profile_url=social_network['profile_url'].strip(), ) checked_social_networks_data.append(social_network_dict) return checked_social_networks_data
def _add_or_update_custom_fields(custom_fields, user): """ - Duplicate dict(s) will be removed - Custom field ID(s) must be recognized and must belong to user's domain """ # Remove duplicate data custom_fields = remove_duplicates(custom_fields) # Custom field IDs must belong to candidate's domain custom_field_ids = [ custom_field['custom_field_id'] for custom_field in custom_fields ] if not db.session.cquery(CustomField).filter( CustomField.id.in_(custom_field_ids), CustomField.domain_id != user.domain_id).count() == 0: raise ForbiddenError(FORBIDDEN_CUSTOM_FIELDS[0], FORBIDDEN_CUSTOM_FIELDS[1]) # TODO: track updates return map(purge_dict, custom_fields)
def _add_or_update_references(references, is_updating, user_id, candidate_id, existing_data): # Remove duplicate data references = remove_duplicates(references) # Aggregate formatted & validated references' data validated_references_data = [] for index, reference in enumerate(references): reference_dict = dict(reference_name=reference.get('person_name'), position_title=reference.get('position_title'), comments=reference.get('comments')) # Remove empty data reference_dict = purge_dict(reference_dict) # Prevent adding empty records if not reference_dict: continue validated_references_data.append(reference_dict) return validated_references_data
def _add_or_update_notes(notes, user_id, is_updating, candidate_id, existing_data): # Remove duplicates notes = remove_duplicates(notes) # Aggregate formatted & validated notes' data validated_notes_data = [] for index, note in enumerate(notes): note_dict = dict(owner_id=user_id, title=note.get('title'), comments=note['comments']) # Remove empty data note_dict = purge_dict(note_dict) # Prevent adding empty records if not note_dict: continue validated_notes_data.append(note_dict) return validated_notes_data
def _add_or_update_skills(skills, is_updating, user_id, candidate_id, existing_data): # Remove duplicate data skills = remove_duplicates(skills) # Aggregate formatted & validated skills' data validated_skills_data = [] for index, skill in enumerate(skills): skill_dict = dict(name=skill.get('name'), months_used=skill.get('months_used'), last_used_year=skill.get('last_used_year'), last_used_month=skill.get('last_used_month')) # Remove empty data skill_dict = purge_dict(skill_dict) # Prevent adding empty records if not skill_dict: continue validated_skills_data.append(skill_dict) return validated_skills_data
def _add_or_update_phones(phones, is_updating, user_id, candidate_id, existing_data): # Remove duplicates phones = remove_duplicates(phones) # Aggregate formatted & validated phones' data validated_phones_data = [] # Check if phone label and default have been provided phones_have_label = any([phone.get('label') for phone in phones]) phones_have_default = any( [isinstance(phone.get('is_default'), bool) for phone in phones]) # If duplicate phone numbers are provided, we will only use one of them seen = set() for phone in phones: phone_value = phone.get('value') if phone_value and phone_value in seen: phones.remove(phone) seen.add(phone_value) for index, phone in enumerate(phones): # If there is no default value, the first phone should be set as the default phone is_default = index == 0 if not phones_have_default else phone.get( 'is_default') # If there's no label, the first phone's label will be 'Home', rest will be 'Other' phone_label = 'Mobile' if (not phones_have_label and index == 0) else clean( phone.get('label')) # Phone number must contain at least 7 digits # http://stackoverflow.com/questions/14894899/what-is-the-minimum-length-of-a-valid-international-phone-number value = clean(phone.get('value')) number = re.sub('\D', '', value) if len(number) < 7: # TODO: for now, we will just need to log this but do not raise an exception logger.info( "Phone number ({}) must be at least 7 digits".format(value)) iso3166_country_code = phone.get('iso3166_country') phone_number_obj = parse_phone_number( value, iso3166_country_code=iso3166_country_code) if value else None """ :type phone_number_obj: PhoneNumber """ # phonenumbers.format() will append "+None" if phone_number_obj.country_code is None if phone_number_obj: if not phone_number_obj.country_code: value = str(phone_number_obj.national_number) else: value = str( phonenumbers.format_number( phone_number_obj, phonenumbers.PhoneNumberFormat.E164)) phone_dict = dict( value=value, extension=phone_number_obj.extension if phone_number_obj else None, label=phone_label, is_default=is_default) # Remove empty data phone_dict = purge_dict(phone_dict) # Prevent adding empty records if not phone_dict: continue # Save data validated_phones_data.append(phone_dict) return validated_phones_data
def _add_or_update_experiences(experiences, is_updating, user_id, candidate_id, existing_data): # Remove duplicates experiences = remove_duplicates(experiences) # Aggregate formatted & validated experiences data validated_experiences_data = [] # Identify experiences' maximum start year latest_start_year = max( experience.get('start_year') for experience in experiences) for index, experience in enumerate(experiences): start_year, end_year = experience.get('start_year'), experience.get( 'end_year') is_current = experience.get('is_current') # End year of experience must be none if it's candidate's current job if is_current: end_year = None if start_year: # If end_year is not provided and experience is candidate's current job, set end year to current year if not end_year and (start_year == latest_start_year): end_year = datetime.utcnow().year # if end_year is not provided, and it's not the latest job, end_year will be latest job's start_year + 1 elif not end_year and (start_year != latest_start_year): end_year = start_year + 1 # Start year must not be greater than end year if (start_year and end_year) and start_year > end_year: raise Exception country_code = clean(experience.get('iso3166_country')).upper() subdivision_code = clean(experience.get('iso3166_subdivision')).upper() experience_dict = dict( organization=clean(experience.get('organization')), position=clean(experience.get('position')), city=clean(experience.get('city')), iso3166_subdivision=subdivision_code, iso3166_country=country_code, start_year=start_year, start_month=experience.get('start_month') or 1, end_year=end_year, end_month=experience.get('end_month') or 1, is_current=is_current, description=clean(experience.get('description'))) # Remove empty data experience_dict = purge_dict(experience_dict) # Prevent adding empty records if not experience_dict: continue # TODO: accumulate total months experience for candidate validated_experiences_data.append(experience_dict) return validated_experiences_data
def _add_or_update_educations(educations, is_updating, user_id, candidate_id, existing_data): """ - Duplicate dict(s) will be removed - """ # Remove duplicate data education_items = None for i, education in enumerate(educations): if education.items() == education_items: del educations[i] else: education_items = education.items() # Aggregate formatted & validated education data validated_education_data = [] for index, education in enumerate(educations): education_dict = dict( school_name=education.get('school_name'), school_type=education.get('school_type'), city=education.get('city'), iso3166_country=(education.get('iso3166_country') or '').upper(), iso3166_subdivision=(education.get('iso3166_subdivision') or '').upper(), state=(education.get('state') or '').upper(), is_current=education.get('is_current')) # Remove empty data education_dict = purge_dict(education_dict) # Prevent adding empty records if not education_dict: continue validated_education_data.append(education_dict) degrees = education.get('degrees') if degrees: # Remove duplicates degrees = remove_duplicates(degrees) # todo: may not be necessary # Aggregate formatted & validated degree data checked_degree_data = [] for i, degree in enumerate(degrees): degree_dict = dict( start_year=degree.get('start_year'), start_month=degree.get('start_month'), end_year=degree.get('end_year'), end_month=degree.get('end_month'), gpa=str(degree['gpa']) if degree.get('gpa') else None, title=degree.get('title'), concentration=degree.get('concentration'), comments=degree.get('comments')) # Remove empty data degree_dict = purge_dict(degree_dict) print("degree_dict: {}".format(degree_dict)) # Prevent adding empty records if not degree_dict: continue checked_degree_data.append(degree_dict) # Aggregate degree data to the corresponding education data validated_education_data[index]['degrees'] = checked_degree_data print("validated_education_data: {}".format(validated_education_data)) return validated_education_data