Some environments require that data that is privacy-related or contains PII be catalogued such that we know what is stored, where it is stored and why it is stored. This article outlines functionality built for HRSD which produces a report of privacy related fields for each HR Service.
The end result is an html “report” which provides an overview of each service and the privacy-related data contained within it. For example:
Change of Beneficiaries Request – This service allows employees to change the beneficiaries for their health insurance benefits.
- Fields on intake form
- Beneficiary name
- Beneficiary date of birth
- Fields on provider form
- Beneficiary last enrolled date
- Associated forms
- 342.44 Beneficiaries Change
UI Actions
The report is run via client UI Actions on the HR Service Configuration form.
Name: Show Privacy Report for this Service
Client: True
Onclick: showPrivacyReport()
Condition: gs.hasRole(‘sn_hr_core.admin’) (usually only HR admins will run this)
Script:
function showPrivacyReport() {
var glideAjax = new GlideAjax("sn_hr_core.HRSDPrivacyReportUtils");
glideAjax.addParam('sysparm_name', 'getServiceReportClient');
glideAjax.addParam('sysparm_servicesysid', g_form.getUniqueValue());
glideAjax.getXMLAnswer(function(response) {
var gm = new GlideModal();
//Sets the dialog title
gm.setTitle('Privacy Report');
gm.setWidth(800);
//Opens the dialog
gm.renderWithContent(response);
}
);
}
Name: Show Privacy Report All Active Services
Client: True
Onclick: showPrivacyReportAll()
Condition: gs.hasRole(‘sn_hr_core.admin’) (usually only HR admins will run this)
Script:
function showPrivacyReportAll() {
var glideAjax = new GlideAjax("sn_hr_core.HRSDPrivacyReportUtils");
glideAjax.addParam('sysparm_name', 'getServiceReportAllActiveServices');
glideAjax.getXMLAnswer(function(response) {
var gm = new GlideModal();
//Sets the dialog title
gm.setTitle('Privacy Report');
gm.setWidth(800);
//Opens the dialog
gm.renderWithContent(response);
}
);
}
Customer Fields on HR Service Configuration Table
Create a new section in the HR Service Configuration table (sn_hr_core_service) for the new fields
![](https://incident.do/wp-content/uploads/2024/11/image-1-1024x264.png)
- Description for Privacy – u_description_privacy – string 4000
- Exclude this service from the privacy report – u_exclude_from_privacy_report – true/false
- Intake Form (Record Producer) Fields for Privacy Report -u_record_producer_fields – List
- Reference table: item_option_new
- Reference qualifier: javascript: ‘active=true^cat_item=’ + current.producer;
- Include all Intake Form fields in Privacy Report – u_all_intake_fields_privacy_report – true/false
- Provider Fields for Privacy Report – u_table_fields_privacy_report – List
- Reference table: sys_dictionary
- Reference qualifier: javascript:’active=true^name=task^ORname=sn_hr_core_case^ORname=’ + current.topic_detail.topic_category.coe
- HR Forms for Privacy Report – u_hr_forms – list
- Reference table: sn_hr_core_forms (this is a custom table extended from dl_matcher)
- Reference table: sn_hr_core_forms (this is a custom table extended from dl_matcher)
Custom Table to Store Forms
If you have a list of PDF forms for HR used in the organization, you can create a table to store them (extended from dl_matcher table). You could also store these in Document Templates or in a table extended from the CMDB.
Table Name: HR Forms sn_hr_core_forms
Extended from: dl_matcher
Fields
- Name – u_name – string 100
- Title – u_title – string 100
Script Include
Name: HRSDPrivacyReportUtils
Client callable: True
var HRSDPrivacyReportUtils = Class.create();
HRSDPrivacyReportUtils.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
//returns the html of the report for all HR Services
getServiceReportAllActiveServices: function() {
var html = '<ul>';
var serviceGR = new GlideRecord('sn_hr_core_service');
serviceGR.addActiveQuery();
serviceGR.addQuery('u_exclude_from_privacy_report', false);
serviceGR.query();
while (serviceGR.next()) {
html += this.getServiceReport(serviceGR);
}
html += '</ul>';
return html;
},
//client callable (takes sys_id instead of gliderecord) method to get the html of the privacy report for a single HR service.
getServiceReportClient: function() {
var servicesysid = this.getParameter('sysparm_servicesysid');
var serviceGR = new GlideRecord('sn_hr_core_service');
serviceGR.get(servicesysid);
var result = this.getServiceReport(serviceGR);
return result;
},
//gets the html privacy report for a single HR Service
getServiceReport: function(serviceGR) {
var html = "<li>";
html += "<strong>" + serviceGR.name.getDisplayValue() + "</strong>";
var description = serviceGR.u_description_privacy.getDisplayValue();
if (description) {
html += " - " + description;
}
html += '<ul>';
//record producer (intake form) fields selected for the privacy report on the HR Service Configuration form.
if (serviceGR.u_record_producer_fields || serviceGR.u_all_intake_fields_privacy_report) {
html += "<li> Fields included on intake form: ";
if (serviceGR.u_all_intake_fields_privacy_report) {
html += this.getVariables(null, serviceGR.getValue('producer'),null);
} else {
html += this.getVariables(serviceGR.getValue('u_record_producer_fields'), null,null);
}
html += "</li>";
}
// table fields selected for the privacy report on the HR Service Configuration form.
if (serviceGR.u_table_fields_privacy_report) {
html += "<li> Fields included in provider view: " + this.getFields(serviceGR.getValue('u_table_fields_privacy_report'));
html += "</li>";
}
//federal hr forms selected for the privacy report on the HR Service Configuration form.
if (serviceGR.u_federal_hr_forms) {
var forms = this.getFederalHRForms(serviceGR);
html += "<li> Forms associated with this service: " + forms;
html += "</li>";
}
html += '</ul>';
html += "</li>";
return html;
},
//gets information on the variables
getVariables: function(variableSysIds, catItemSysId, variableSetSysId) {
var result = '';
//if(!variableSetSysId){
result += '<ul>';
//}
//check if the catalog item has variable sets
var variableSetsArr;
var currentOrder = -1;
if(catItemSysId){
variableSetsArr = this.getVariableSetsForRecordProducer(catItemSysId);
if(variableSetsArr){
currentOrder = 0;
}
}
var variablesGR = new GlideRecord('item_option_new');
if (variableSysIds) {
variablesGR.addQuery('sys_id', 'IN', variableSysIds);
} else if (variableSetSysId){
variablesGR.addActiveQuery();
variablesGR.addQuery('variable_set', variableSetSysId);
} else {
variablesGR.addActiveQuery();
variablesGR.addQuery('cat_item', catItemSysId);
variablesGR.addEncodedQuery('typeNOT IN20,24,19,32'); //no containers or rich text
}
variablesGR.orderBy('order');
variablesGR.query();
while (variablesGR.next()) {
if(currentOrder >= 0){
if(variablesGR.getValue('order') > variableSetsArr[currentOrder].order){
result += this.getVariableSet(variableSetsArr[currentOrder].sys_id);
if(currentOrder == (variableSetsArr.length - 1)){
currentOrder = -1;
} else {
currentOrder ++;
}
}
}
result += '<li>' + variablesGR.question_text.getDisplayValue() + ' (' + variablesGR.type.getDisplayValue();
if (variablesGR.getValue('type') == '3') { //multiple choice
result += ': ';
result += this.getVariableChoices(variablesGR);
result += ')';
} else if (variablesGR.getValue('type') == '8') { //reference
result += ': List of values from the ';
result += this.getTableLabel(variablesGR.reference.getDisplayValue());
result += ' table)';
} else if (variablesGR.getValue('type') == '21') { // list collector
result += ' for multiple selections: List of values from the ';
result += this.getTableLabel(variablesGR.list_table.getDisplayValue());
result += ' table)';
} else if (variablesGR.getValue('type') == '5') { // select box
result += ': ';
if (variablesGR.choice_table) {
result += this.getTableChoices(variablesGR.getValue('choice_table'), variablesGR.getValue('choice_field'));
} else {
this.getVariableChoices(variablesGR)
}
result += ')';
} else {
result += ')';
}
result += '</li> ';
}
//if(!variableSetSysId){
result += '</ul>';
//}
return result;
},
//gets the choices for a select variable
getVariableChoices: function(variableGR) {
var result = '';
var choicesGR = new GlideRecord('question_choice');
choicesGR.addQuery('question', variableGR.getUniqueValue());
choicesGR.addQuery('inactive', false);
choicesGR.orderBy('order');
choicesGR.query();
while (choicesGR.next()) {
if (result) {
result += ', ';
}
result += choicesGR.text.getDisplayValue();
}
return result;
},
//gets the label for a table
getTableLabel: function(tableName) {
var dictGR = new GlideRecord('sys_db_object');
dictGR.get('name', tableName);
return dictGR.label.getDisplayValue();
},
//gets the choices for a choice field
getTableChoices: function(tableName, element) {
var result = '';
var choicesGR = new GlideRecord('sys_choice');
choicesGR.addQuery('name', tableName);
choicesGR.addQuery('element', element);
choicesGR.addQuery('inactive', false);
choicesGR.orderBy('order');
choicesGR.query();
while (choicesGR.next()) {
if (result) {
result += ', ';
}
result += choicesGR.label.getDisplayValue();
}
return result;
},
//gets information on the fields
getFields: function(fieldList) {
var result = '';
var dictGR = new GlideRecord('sys_dictionary');
dictGR.addQuery('sys_id', 'IN', fieldList);
dictGR.query();
while (dictGR.next()) {
if (result) {
result += '; ';
}
result += dictGR.column_label.getDisplayValue() + ' (' + dictGR.internal_type.getDisplayValue();
if (dictGR.getValue('internal_type') == 'Choice') { //choice
result += ': ';
result += this.getTableChoices(dictGR.getValue('name'), dictGR.getValue('element'));
result += ')';
} else if (dictGR.getValue('internal_type') == 'reference') { //reference
result += ': List of values from the ';
result += dictGR.reference.getDisplayValue();
result += ' table)';
} else if (dictGR.getValue('internal_type') == 'glide_list') { //reference
result += ' for multiple selections: List of values from the ';
result += dictGR.reference.getDisplayValue();
result += ' table)';
} else {
result += ')';
}
}
// }
return result;
},
//gets information on the forms
getFederalHRForms: function(serviceGR) {
result = '';
var formsGR = new GlideRecord('sn_hr_core_forms');
formsGR.addQuery('sys_id', 'IN', serviceGR.getValue('u_federal_hr_forms'));
formsGR.query();
while (formsGR.next()) {
if (result) {
result += '; ';
}
result += formsGR.u_name.getDisplayValue() + ' - ' + formsGR.u_title.getDisplayValue();
}
return result;
},
getVariableSet: function(variableSetSysId) {
var result = '';
var variableSetGR = new GlideRecord('item_option_new_set');
variableSetGR.get(variableSetSysId);
if (variableSetGR.getValue('type') == 'one_to_many') {
result += '<li>';
result += variableSetGR.title.getDisplayValue();
result += " (Multi-row input) ";
result += this.getVariables(null,null,variableSetGR.getUniqueValue());
result += '</li>';
}
else {
result += this.getVariables(null,null,variableSetGR.getUniqueValue());
}
return result;
},
getVariableSetsForRecordProducer: function(recordProducerSysId){
var result = [];
var setGR = new GlideRecord('io_set_item');
setGR.addQuery('sc_cat_item',recordProducerSysId);
setGR.query();
while(setGR.next()){
var obj = {};
obj.sys_id = setGR.getValue('variable_set');
obj.order = setGR.getValue('order');
result.push(obj);
}
return result;
},
type: 'HRSDPrivacyReportUtils'
});