Name

sn_hr_core.hr_Profile

Description

Handles HR Profile records

Script

var hr_Profile = Class.create();

// Place field names that do not map directly from the Record Producer to the HR Profile.
// example:
//     	"work_email": "email"
//      - maps value in RP:parameters[work_email] into new gr:profile[email]
hr_Profile.rpToProfileMap = {
  		"change_date": "employment_start_date"
};
  			
// Do not show these fields in the approval list, and in profile/user updates; users
// do not get to change these.
hr_Profile.userProfileBlacklist = {
  		"active" : "",
  		"user": "",
  		"name": "" ,
  		"workday_transaction_log": "", // This line of code is required for customers upgrading to Madrid from a previous version. If you upgrade your instance, do not delete this line.
  		"number": "",
  		"offboard_type": "",
  		"ssn_display": ""
};

hr_Profile.usaEmployeeFieldMap = {
  		"user.employee_number"  : "EmployeeIdentifier",
  		"user.first_name"       : "FirstName",
  		"user.middle_name"      : "MiddleName",
  		"user.last_name"        : "LastName",
  		"user.introduction"     : "Suffix",
  		"user.email"            : "Email",
  		"date_of_birth"         : "BirthDate",
  		"employment_start_date" : "HireDate",
  		"user.company"          : "Company",
  		"address"               : "ResidenceAddress",
  		"city"                  : "ResidenceCity",
  		"state"                 : "ResidenceState",
  		"zip"                   : "ResidencePostalCode",
  		"country"               : "ResidenceCountry",
  		"location.street"       : "WorkAddress",
  		"location.city"         : "WorkCity",
  		"location.state"        : "WorkState",
  		"location.zip"          : "WorkPostalCode",
  		"location.country"      : "WorkCountry"
};
  			
hr_Profile.prototype = {
  		initialize: function(_gr, _gs) {
  			this._gr = _gr;
  			this._gs = _gs || gs;
  		},
  
  		/**
  		* Creates an sn_hr_core_profile record from a parameter list and links it
  		* to the sys_user record
  		* @param  parameters object map that contain name/value pairs from the RP
  		* @return fully populated sn_hr_core_profile record
  		*/
  		createOrGetProfileFromParameters: function(parameters) {
  			var fname = parameters['first_name'];
  			var lname = parameters['last_name'];
  			var email = parameters['personal_email'];
  			
  			//get the user from first name / last name
  			var userGr = hr_SysUser.instance.getSysUserRecordFromNames(fname,lname);
  			//get the hr profile based on unique key
  			var profile = this.getProfileFromUniqueKey(fname, lname, email);
  			
  			// if user and associated profile record is null then create new profile 
  			// along with user and return the newly created profile
  			if (gs.nil(userGr) || gs.nil(profile))
  				return this._createProfileFromParameters(parameters, null);
  			
  			//activate the user if not activated
  			if (!(profile.user.active)) {
  				var params = {};
  				params.active = true;
  				hr_SysUser.instance.updateSysUserFromParams(profile.user.getUniqueValue(), params);
  			}
  			//if user and profile exists then return the updated the hr profile 
  			return this._updateProfileFromParameters(profile, parameters);
  		},
  		
  		/**
  		* Tests for an sn_hr_core_profile/sys_user record that contains the specified UserID
  		*
  		* @param user user field of record being searched
  		* @return glide record of sn_hr_core_profile if record exists for this field combination,
  		*         null otherwise
  		*/
  		getProfileFromUser: function(userId) {
  			var hrProfile = new GlideRecord(hr.TABLE_PROFILE);
  			return (hrProfile.get('user', userId))? hrProfile: null;
  		},
  		
  		/**
  		* Tests for an sn_hr_core_profile/sys_user record that matches the fields
  		* that unique profile rule.
  		*
  		* Note, fname and lname are stored in the sys_user table and verified through
  		* a reference lookup
  		*
  		* @param fname field first_name of the user record being searched
  		* @param lname field last_name of the user record being searched
  		* @param email field personal_email of the user record being searched
  		* @return glide record of sn_hr_core_profile if record exists for this field combination,
  		*         null otherwise
  		*/
  		getProfileFromUniqueKey: function(fname, lname, email) {
  			var hrProfile = new GlideRecord(hr.TABLE_PROFILE);
  			hrProfile.addQuery('user.first_name', fname); // From sys_user table
  			hrProfile.addQuery('user.last_name', lname);  // From sys_user table
  			hrProfile.addQuery('personal_email', email);
  			hrProfile.query();
  			
  			return (hrProfile.next())? hrProfile: null;
  		},
  		
  		getProfileFromParameters: function(parameters) {
  			var user = parameters['opened_for'] || parameters['user'];
  			var hrProfile = new GlideRecord(hr.TABLE_PROFILE);
  			
  			// Find a profile with thie requested User and return it
  			if (hrProfile.get('user', user))
  				return hrProfile;
  			
  			// Else, we create a profile from User and return it; might be null if
  			// user id does not match a User record
  			return this._createProfileFromUser(user, parameters);
  		},
  		
  		getProfileFromId: function(profileId) {
  			var hrProfile = new GlideRecord(hr.TABLE_PROFILE);
  			return (hrProfile.get(profileId))? hrProfile: null;
  		},
  		
  		getDisplayValue: function(grprofile, fieldName, display) {
  			var translatedField = hr_Profile.rpToProfileMap[fieldName] || fieldName;
  			
  			var profileDisplayValue = (display) ? grprofile.getDisplayValue(translatedField) : grprofile.getValue(translatedField);
  			var userDisplayValue = hr_SysUser.instance.getDisplayValue(grprofile.user, fieldName, display);
  			
  			if (profileDisplayValue)
  				return profileDisplayValue;
  			if (userDisplayValue)
  				return userDisplayValue;
  			
  			return '';
  		},
  		
  		/**
  		* Creates an HR Profile (and sys_user) record from HR Case record producer
  		* and populates the relevant fields for the variables
  		*
  		* @param  parameters object map that contain name/value pairs from the RP
  		* @param  UserGR sys_user gliderecord
  		* @return the sys_id to a fully populated sn_hr_core_profile record
  		*/
  		_createProfileFromParameters: function(parameters, sysUser) {
  			var hrProfile = new GlideRecord(hr.TABLE_PROFILE);
  			hrProfile.initialize();
  			// Fill in a new sys_user record if not exists
  			if (gs.nil(sysUser))
  				hrProfile.user = hr_SysUser.instance.createUserRecordFromParameters(parameters, false);
  			else
  				hrProfile.user = sysUser.getUniqueValue();
  			
  			// Fill in the profile fields we care about
  			hr_Utils.instance.fillInFromMap(hrProfile, parameters, hr_Profile.rpToProfileMap);
  			
  			// Create the sn_hr_core_profile record
  			var profileId = hrProfile.insert();	
  			
  			if(!gs.nil(profileId) && !gs.nil(parameters) && parameters['onboarding'])				
  				parameters['job'] = hr_Utils.instance.createPrimaryJobFromProfile(hrProfile);

  			return hrProfile;
  		},
  		
  		/**
  		* Updates an HR Profile (and sys_user) record from HR Case record producer
  		* and populates the changed fields for the variables
  		*
  		* @param  parameters object map that contain name/value pairs from the RP
  		* @return fully populated sn_hr_core_profile record
  		*/
  		_updateProfileFromParameters: function(profile, parameters) {
  			if(parameters['onboarding'] && !parameters['job'])
  				parameters['job'] = hr_Utils.instance.createJobFromParameters(profile, parameters, false);
  			else {
  				// Update sys_user record
  				hr_SysUser.instance.updateUserRecordFromParameters(profile.user, parameters);
  				// Make the changes in profile
  				hr_Utils.instance.fillInFromMap(profile, parameters, hr_Profile.rpToProfileMap);
  				profile.update();
  			}

  			return profile;
  		},
  		
  		/*
  		* Convenience method to prevent the code becoming unreadable from the useful debug statements
  		*/
  		_logDebug : function(str) {
  			if (gs.isDebugging())
  				gs.debug(str);
  		},
  		
  		/*
  		* Create profile from sys_user
  		* called from the HR case form button
  		*/
  		createProfileFromUser: function(userId) {
  			var hrProfile = this._createProfileFromUser(userId);
  			if (hrProfile)
  				return hrProfile.getUniqueValue();
  			
  			// only add error message if user has permission to create HR profile and profile is not created
  			var grProfile = new GlideRecord(hr.TABLE_PROFILE);
  			if (grProfile.canCreate())
  				gs.addErrorMessage(gs.getMessage('User record not found'));
  		
  			return null;
  		},
  
  		/* Create or get an HR Profile for a passed in user sys_id
  		 * @param (String) userId - The sys_id of the User to create or find an HR Profile for
  		 * @param (Object) parameters - Parameters to be used when creating an HR Profile
  		 * @return (GlideRecord) - The sn_hr_core_profile record found, created, or attempted to be created for the user @userId
  		 */
  		_createProfileFromUser: function(userId, parameters) {
  			if (this.userHasProfile(userId))
  				return this.getCurrentProfile(userId);
  			
  			var user = new GlideRecord(hr.TABLE_USER);
  			if (!user.get(userId))
  				return null;
  			
  			var hrSync = new hr_Synchronize();
  			var hrProfile = hrSync.syncNewRecord(user);
  			
  			if (!gs.nil(hrProfile)) {
  				hrSync.syncRecord(user, true);

  				if (hrProfile.get(hrProfile.getUniqueValue()) && !gs.nil(parameters) && parameters['onboarding']) {
  					var jobId = hr_Utils.instance.createPrimaryJobFromProfile(hrProfile);
  					parameters['job'] = jobId;
  				}
  			}
  			
  			return hrProfile;
  		},
  		
  		/**
  		* Tests for if sys_user record has a matching HR profile.
  		*
  		* @param userId sys_id field of user
  		* @return true if an sn_hr_core_profile record exists for this userId, false otherwise
  		*/
  		userHasProfile: function(userId) {
  			if (this.getCurrentProfile(userId))
  				return true;
  			else
  				return false;
  		},
  		
  		getCurrentProfile: function(userId) {
  			if (!userId)
  				return null;
  			
  			var gr = new GlideRecord(hr.TABLE_PROFILE);
  			gr.addQuery("user", userId);
  			gr.addActiveQuery();
  			gr.query();
  			if (gr.next() && gr.canRead())
  				return gr;
  			else
  				return null;
  		},
  		
  		canReadProfileFields: function() {
  			if (this._gr.isNewRecord())
  				return true;
  			
  			// Check the hr role
  			if (this._gs.hasRole(hr.ROLE_HR_PROFILE_READER))
  				return true;
  			
  			// Check if the profile is related to the current user
  			var profileUser = this._gr.getValue("user");
  			if (!gs.nil(profileUser) && this._gs.getUserID() == profileUser)
  				return true;
  			
  			// Check if the current user is a manager of the profile
  			if (!gs.nil(profileUser) && new global.HRSecurityUtilsAjax().userReportsTo(profileUser, this._gs.getUserID()))
  				return true;
  			
  			return false;
  		},
  		
  		isCurrentUserRecord: function(current){
  			var employeeUser = current.getValue("user");
  			return !gs.nil(employeeUser) && gs.getUserID() == employeeUser;
  		},
  		
  		// returns a comma separated list of sys_ids of users under a manager (all reports)
  		getAllReports: function(managerId) {
  			var managers = [managerId];
  			var users = '';
  			while (managers.length) {
  				managerId = managers.shift();
  				var gr = new GlideRecord(hr.TABLE_PROFILE);
  				gr.addNotNullQuery('manager');
  				gr.addQuery('manager', managerId);
  				gr.addActiveQuery();
  				gr.query();
  				while (gr.next()) {
  					if (users == '') {
  						users += gr.sys_id;
  						managers.push(gr.user.sys_id);
  					}
  					if (users.indexOf(gr.sys_id) == -1) {
  						users += ',' + gr.sys_id;
  						managers.push(gr.user.sys_id + '');
  					}
  				}
  			}
  			return users;
  		},
  		
  		getProfileFields: function() {
  			if (!hr_Profile.profileFields) {
  				var profileFields = hr_Utils.instance.getFieldsFromTable(hr.TABLE_PROFILE, null, hr_Profile.userProfileBlacklist);
  			
  				// Add the profile related fields that are supported in the SysUser table as well
  				var userFields = hr_SysUser.instance.getUserProfileFields();
  				for (var userField in userFields)
  					profileFields[userField] = userFields[userField];
  			
  				hr_Profile.profileFields = profileFields;
  			}
  			return hr_Profile.profileFields;
  		},

  		/* This API is deprecated. It may be removed in the next release */
  		getRPFieldsFromId: function(profileId) {
  			var rpFields = {};
  			var grProfile = new GlideRecordSecure(hr.TABLE_PROFILE);
  			if (grProfile.get(profileId)) {
  					if (!hr_Profile.tableFields)
  						hr_Profile.tableFields = hr_Utils.instance.getFieldsFromTable(hr.TABLE_PROFILE);  // cache tableFields
  				
  					for (var field in hr_Profile.tableFields) {
  						rpFields[field] = {};
  							rpFields[field].value = grProfile.getValue(field);
  							rpFields[field].displayValue = grProfile.getDisplayValue(field);
  					}
  			}
  					
  			// Add the profile fields that are supported in the SysUser table as well
  			var userFields = hr_SysUser.instance.getRPFieldsFromId(grProfile.getValue("user"));
  			for (var userField in userFields)
  				rpFields[userField] = userFields[userField];
  					
  			return rpFields;
  		},

  		getRPFieldsFromUserId: function(userId) {
  					var rpFields = {};
  					// Add the profile fields that are supported in the SysUser table as well
  					var userFields = hr_SysUser.instance.getRPFieldsFromId(userId);
  					for (var userField in userFields) {
  						if (userField!=='country')
  								rpFields[userField] = userFields[userField];
  					}
  					var grProfile = new GlideRecordSecure(hr.TABLE_PROFILE);
  					if (grProfile.get('user', userId)) {
  							if (!hr_Profile.tableFields)
  								hr_Profile.tableFields = hr_Utils.instance.getFieldsFromTable(hr.TABLE_PROFILE);  // cache tableFields
  						
  							for(var field in hr_Profile.tableFields) {
  								var value = grProfile.getValue(field);
  								if (value == null || value === 'null')
  									continue;
  								
  								rpFields[field] = {};
  								rpFields[field].value = value;
  								rpFields[field].displayValue = grProfile.getDisplayValue(field);
  							}
  					}
  					return rpFields;
  		},
  						
  		/*
  		 * Validates if user profile already exists
  		 *
  		 * @param first name - First Name of employee
  		 * @param last name - Last name of employee
  		 * @param email - personal email address of user; if empty return true
  		 * @return boolean whether the user profile exists.
  		 */
  		validateUserProfileRecord: function(first_name, last_name, email) {
  					if (!email || email == 'null' || email == 'NULL')
  							return true;
  			
  					email = email + '';
  					if (email.trim() == '')
  							return true;
  			
  					var profileRecord = new GlideRecord(hr.TABLE_PROFILE);
  					profileRecord.addQuery("user.first_name", first_name);
  					profileRecord.addQuery("user.last_name", last_name);
  					profileRecord.addQuery("personal_email", email);
  					profileRecord.query();

  					return profileRecord.getRowCount() == 0;
  		},	
  							
  		updateProfile: function(caseId, profileId) {
  			var grProfile = new GlideRecord(sn_hr_core.hr.TABLE_PROFILE);
  			if (grProfile.get(profileId)) {
  				hr_SysUser.instance.updateSysUser(caseId, grProfile.user);

  				var qa = new GlideRecord("question_answer");
  				qa.addQuery('table_name', 'IN', hr.TABLE_CASE_EXTENSIONS);
  				qa.addQuery('table_sys_id', caseId);
  				qa.query();

  				while (qa.next()) {
  					var translatedField = hr_Profile.rpToProfileMap[qa.question.name] || qa.question.name;

  					if (grProfile.isValidField(translatedField)){
  						//Is the new value is changed
  						if (grProfile.getValue(translatedField) != qa.getValue("value")) {
  							//Query fails if newValue is null
  							var newValue = qa.getValue("value")? qa.getValue("value") : "";
  							grProfile.setValue(translatedField, newValue);
  						}
  					}
  				}
  				if (grProfile.update())
  					gs.addInfoMessage(gs.getMessage('Profile updated successfully'));
  				else
  					gs.addErrorMessage(gs.getMessage('Profile not updated'));
  			}
  		},
  
  		/**
  		 * Checks if user has access to any of document types in order to create a new employee document
  		 **/
  		hasAccesstoDocumentTypes: function () {
  			if (new GlidePluginManager().isActive('com.sn_employee_document_management')) 
  				return new sn_hr_ef.ef_Utils().getDocTypesForSelection('hr').length > 0;
  			else
  				return false;
  		},

  		/**
  		 * Updates the leave status for an employee's HR Profile based on the 
  		 * related leave status records
  		 * @param {String} userId - the employee user ID
  		 */
  		updateLeaveStatus: function(userId) {
  			var hrProfile = new GlideRecord(sn_hr_core.hr.TABLE_PROFILE);
  			if (!hrProfile.get('user', userId))
  				return;
  			
  			var status = 'not_on_leave';
  			if (this._hasOneOrMoreLeaves(userId, 'on_leave'))
  				status = 'on_leave';
  			else if (this._hasOneOrMoreLeaves(userId, 'approved'))
  				status = 'approved';
  			else if (this._hasOneOrMoreLeaves(userId, 'requested'))
  				status = 'requested';
  			
  			hrProfile.leave_status = status;
  			hrProfile.update();
  		},

  		/**
  		 * @param {String} userId - the user id
  		 * @param {String} status - the status to query for
  		 * @return {Boolean} - true if the user has one or more leaves
  		 *   in the status
  		 */
  		_hasOneOrMoreLeaves: function(userId, status) {
  			var leave = new GlideRecord(hr.TABLE_LEAVE_OF_ABSENCE);
  			leave.addQuery('employee', userId);
  			leave.addQuery('leave_status', status);
  			leave.setLimit(1);
  			leave.query();
  			return leave.hasNext();
  		},
  
  		getUSAUserHrProfile: function(empNumber,sysUpdatedOn,numberOfRecords,startRow){

  			var result ={};
  			result.employeeInformation =[];
  			result.nextPage = false;

  			var grProfile = new GlideRecord(hr.TABLE_PROFILE);
  			var grTemp = grProfile.addQuery("country.iso3166_3", "USA");
  			grTemp.addOrCondition("location.country", "USA");

  			if (!gs.nil(empNumber)) {
  				empNumber = GlideStringUtil.escapeHTML(empNumber);
  				grProfile.addQuery("user.employee_number", empNumber);
  			}
  			else {
  				numberOfRecords = this._getLimit(numberOfRecords);

  				if (!gs.nil(sysUpdatedOn)) {
  					sysUpdatedOn = this._generateDateTimeStr(sysUpdatedOn);
  					grProfile.addQuery('sys_updated_on', '>=', sysUpdatedOn);
  				}

  				if (!gs.nil(startRow)) {
  					startRow = parseInt(GlideStringUtil.escapeHTML(startRow));
  					grProfile.chooseWindow(startRow, startRow + numberOfRecords + 1);
  				}
  				else
  					grProfile.setLimit(numberOfRecords + 1 );
  				grProfile.orderBy('sys_updated_on');
  			}

  			grProfile.query();

  			while (grProfile.next()) {
  				var userProfile = this._getUserProfile(grProfile);
  				result.employeeInformation.push(userProfile);
  			}

  			if(result.employeeInformation.length > numberOfRecords){
  				result.employeeInformation.pop();
  				result.nextPage = true;
  			}

  			return result;
  		},

  		_getUserProfile: function(grProfile){
  			var userProfile = {};
  				var hrProfileColumns = hr_Profile.usaEmployeeFieldMap;
  				for(var columnName in hrProfileColumns){
  					var value = grProfile.getDisplayValue(columnName);
  					userProfile[hrProfileColumns[columnName]] = value;
  				}
  				userProfile.ReHire ="";
  			return userProfile;
  		},

  		_getLimit: function(numberOfRecords) {
  			var MAX_RESULTS = 100000;

  			if (!gs.nil(numberOfRecords) && numberOfRecords < MAX_RESULTS)
  				numberOfRecords = parseInt(GlideStringUtil.escapeHTML(numberOfRecords));
  			else
  				numberOfRecords = MAX_RESULTS;

  			return numberOfRecords;
  		},


  		//Used in query for time comparison
  		_generateDateTimeStr: function(sysUpdatedOn){
  			sysUpdatedOn = new GlideDateTime(GlideStringUtil.escapeHTML(sysUpdatedOn));
  			sysUpdatedOn = sysUpdatedOn.toString();
  			sysUpdatedOn = sysUpdatedOn.split(" ");
  			var date = sysUpdatedOn[0];
  			var time = sysUpdatedOn[1];
  			return "javascript:gs.dateGenerate('"+date+"','"+time+"')";
  		},

  		type: "hr_Profile"
};

Sys ID

ba5370019f22120047a2d126c42e7000

Offical Documentation

Official Docs: