- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
2 hours ago
Requirement Overview
The core objective is to automate the extraction of modified user attributes from the Lifecycle Event (LE) Case and its associated records. When a transfer occurs, the system must:
- Identify the specific fields changed (e.g., Department, Job Code, Business Unit).
- Compare the previous values (Old) with the current values (New).
- Construct a secure JSON payload and transmit it to Okta to ensure downstream access is updated accurately
Technical Implementation
1. Data Extraction Logic
Script Include: IC_Transfer_FieldHistory_OKTA_Payload
It takes the HR case sys_id, identifies the subject person, and retrieves old and new field values from ServiceNow field history records (sys_audit / history data) using IC_Transfer_GetFieldValues_FromHistory.
User-related changes (department, job code, employee type, title) and HR profile changes (region, company, country, workday location) are fetched from their respective tables.
All old and new values are consolidated into a structured JSON response for integration use.
Client Callable script include Code and scope is Human Resources: Lifecycle Events
var IC_Transfer_FieldHistory_OKTA_Payload_= Class.create();
IC_Transfer_FieldHistory_OKTA_Payload.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
// Function to fetch all field changes (old and new values) for the subject person (sys_id)
getAllFieldChanges: function(caseSysId) {
// Initialize the result object
var result = {
"departmentNames": [],
"departmentIds": [], // Array to store department IDs
"businessUnitNames": [],
"businessUnitIds": [],
"jobCodeChanges": [],
"empTypeChanges": [],
"titleChanges": [],
"hrProfileChanges": {
"regionChanges": [],
"companyChanges": [],
"countryCodeChanges": [],
"workdayLocationChanges": []
}
};
if (!caseSysId) {
gs.error('Sys_id is required to fetch field history');
return 'Sys_id parameter is missing';
}
// Query to fetch the HR case by sys_id
var leCase = new GlideRecord("sn_hr_le_case");
if (leCase.get(caseSysId)) {
var subPerson = leCase.subject_person;
// Fetch and process department-related data
var depChanges = new global.IC_Transfer_GetFieldValues_FromHistory().getFieldChanges('sys_user', subPerson, 'department');
var departmentData = this.getDepartmentAndBusinessUnitData(depChanges);
result.departmentNames = departmentData.names;
result.departmentIds = departmentData.ids; // Add department IDs to result
result.businessUnitNames = departmentData.businessUnitNames;
result.businessUnitIds = departmentData.businessUnitIds;
// Fetch and store other field changes
result.jobCodeChanges = new global.IC_Transfer_GetFieldValues_FromHistory().getFieldChanges('sys_user', subPerson, 'u_job_code');
result.empTypeChanges = new global.IC_Transfer_GetFieldValues_FromHistory().getFieldChanges('sys_user', subPerson, 'x_blglp_workday_in_employee_type');
result.titleChanges = new global.IC_Transfer_GetFieldValues_FromHistory().getFieldChanges('sys_user', subPerson, 'title');
// Fetch HR profile related fields
var hrProfile = new GlideRecord("sn_hr_core_profile");
hrProfile.addQuery('user', subPerson);
hrProfile.query();
if (hrProfile.next()) {
// Store HR profile changes
result.hrProfileChanges.regionChanges = new global.IC_Transfer_GetFieldValues_FromHistory().getFieldChanges('sn_hr_core_profile', hrProfile.sys_id, 'u_region');
result.hrProfileChanges.companyChanges = new global.IC_Transfer_GetFieldValues_FromHistory().getFieldChanges('sn_hr_core_profile', hrProfile.sys_id, 'u_company_name');
result.hrProfileChanges.countryCodeChanges = new global.IC_Transfer_GetFieldValues_FromHistory().getFieldChanges('sn_hr_core_profile', hrProfile.sys_id, 'u_country');
result.hrProfileChanges.workdayLocationChanges = new global.IC_Transfer_GetFieldValues_FromHistory().getFieldChanges('sn_hr_core_profile', hrProfile.sys_id, 'u_workday_location');
}
} else {
gs.error("No HR case found for sys_id: " + caseSysId);
}
// Return the result as a JSON object
return result;
},
type: 'IC_FieldHistory_OKTA_Payload'
});
2. Script Include: IC_Transfer_GetFieldValues_FromHistory
This script is responsible for generating the history set and extracting the specific field transitions (old value and new value) from the sys_history_line table.
var IC_Transfer_GetFieldValues_FromHistory = Class.create();
IC_Transfer_GetFieldValues_FromHistory.prototype = {
initialize: function() {},
getFieldChanges: function(tableName, documentKey, fieldName) {
var changes = [];
var hw, createSet = new GlideRecord(tableName); //to create the history set
createSet.get(documentKey);
try {
var historySetRec = new GlideHistorySet(tableName, documentKey);
historySetRec.generate();
GlideHistorySet(tableName, documentKey).refresh();
} catch (e) {
gs.info("COMPARISONTIME ERROR: " + e);
}
var historySet = new GlideRecord("sys_history_set");
historySet.addQuery("table", tableName);
historySet.addQuery("id", documentKey);
historySet.query();
if (historySet.next()) {
var historyLine = new GlideRecord("sys_history_line");
historyLine.addQuery('set', historySet.sys_id);
historyLine.addQuery("field", fieldName);
historyLine.addQuery("update_time", ">=", gs.minutesAgo(1440)); // 1440 minutes = 24 hours
historyLine.orderByDesc("update_time");
historyLine.query();
if (historyLine.next()) {
var oldValue = historyLine.getValue('old') || historyLine.getValue('new');
var newValue = historyLine.getValue('new');
changes.push(oldValue, newValue);
} else {
// If no history found, set both old and new to the current value
var currentRecord = new GlideRecord(tableName);
if (currentRecord.get(documentKey)) {
var currentValue = currentRecord.getValue(fieldName);
changes.push(currentValue, currentValue);
}
}
}
return changes;
},
type: 'IC_Transfer_GetFieldValues_FromHistory'
};
3. Payload Construction
Once the history is captured, a Flow Action compiles the data into the final JSON format required by Okta.
Code of flow action Payload
IC-Generate Payload: Generates a complete payload with both old and new user attributes using IC_Transfer_FieldHistory_OKTA_Payload script include
(function execute(inputs, outputs) {
var grHRCase = new GlideRecord(String(inputs.hr_case_table))
grHRCase.get(String(inputs.hr_case_sys_id));
grHRCase.query();
if(grHRCase.next()) {
var caseSysId = String(inputs.hr_case_sys_id);
var getFields = new sn_hr_le.IC_Transfer_FieldHistory_OKTA_Payload();
var getFieldValues = getFields.getAllFieldChanges(caseSysId)
outputs.new_department = getFieldValues.departmentNames[1];
outputs.old_department = getFieldValues.departmentNames[0];
outputs.new_business_unit = getFieldValues.businessUnitNames[1];
outputs.old_business_unit = getFieldValues.businessUnitNames[0];
outputs.old_region = getFieldValues.hrProfileChanges.regionChanges[0];
outputs.new_region = getFieldValues.hrProfileChanges.regionChanges[1];
outputs.old_job_code = getFieldValues.jobCodeChanges[0];
outputs.new_job_code = getFieldValues.jobCodeChanges[1];
var transferEffectiveDateTime = new GlideDateTime(grHRCase.u_effective_date);
var transferEffectiveTime = String(transferEffectiveDateTime).replace(" ", "T") + "Z";
var payload = {
"user_id": String(grHRCase.subject_person.employee_number),
"event": {
"id": String(grHRCase.number),
"type": String(inputs.event_type),
"status": String(inputs.status),
"details": {
"SNOW_RITM": String(inputs.provision_access_ritm),
"effective_time": String(transferEffectiveTime),
"old_user_attributes":{
"firstName": String(grHRCase.subject_person_hr_profile.legal_first_name),
"lastName": String(grHRCase.subject_person_hr_profile.u_legal_last_name),
"userType": String(getFieldValues.empTypeChanges[0].toUpperCase()),
"wd_jobCode": String(getFieldValues.jobCodeChanges[0]),
"title": String(getFieldValues.titleChanges[0]),
"division": String(getFieldValues.businessUnitNames[0]),
"wd_BusinessUnitID": String(getFieldValues.businessUnitIds[0]),
"department": String(getFieldValues.departmentNames[0]),
"wd_DepartmentID": String(getFieldValues.departmentIds[0]),
"wd_region": String(getFieldValues.hrProfileChanges.regionChanges[0]),
"countryCode": String(getFieldValues.hrProfileChanges.countryCodeChanges[0]),
"wd_location": String(getFieldValues.hrProfileChanges.workdayLocationChanges[0]),
"wd_company": String(getFieldValues.hrProfileChanges.companyChanges[0])
},
"new_user_attributes":{
"firstName": String(grHRCase.subject_person_hr_profile.legal_first_name),
"lastName": String(grHRCase.subject_person_hr_profile.u_legal_last_name),
"userType": String(getFieldValues.empTypeChanges[1].toUpperCase()),
"wd_jobCode": String(getFieldValues.jobCodeChanges[1]),
"title": String(getFieldValues.titleChanges[1]),
"division": String(getFieldValues.businessUnitNames[1]),
"wd_BusinessUnitID": String(getFieldValues.businessUnitIds[1]),
"department": String(getFieldValues.departmentNames[1]),
"wd_DepartmentID": String(getFieldValues.departmentIds[1]),
"wd_region": String(getFieldValues.hrProfileChanges.regionChanges[1]),
"countryCode": String(getFieldValues.hrProfileChanges.countryCodeChanges[1]),
"wd_location": String(getFieldValues.hrProfileChanges.workdayLocationChanges[1]),
"wd_company": String(getFieldValues.hrProfileChanges.companyChanges[1])
}
}
}
}
outputs.payload = JSON.stringify(payload);
}
})(inputs, outputs);
If my article helped you, please mark it as helpful.
Thank you!
- 13 Views