Name
sn_hr_core.hr_TemplateUtils
Description
No description available
Script
var hr_TemplateUtils = Class.create();
hr_TemplateUtils.prototype = {
initialize: function() {
this._appliedTemplates = {};
},
/**
* applyBefore and applyAfter are intended to be used in conjunction with before and after business rules
* This is to prevent overwriting input changes from the user or email/producer/script
**/
/* Apply a template to a record only, attempt to prevent overwriting user changes
* @param templateSysId : sys_id of the template to apply
* @param record : Optional GlideRecord to apply the template to
* @param overwrite : Optional Boolean Overwrite record values with template values
*/
applyBefore: function(templateSysId, record, overwrite) {
// Setup template and record GlideRecords
var templateGr = new GlideRecord('sn_hr_core_template');
if (!templateGr.get(templateSysId) || !templateGr.active)
return;
if (!record)
record = new GlideRecord(templateGr.getValue('table'));
if (record.isValidField('template'))
record.setValue('template', templateSysId);
if (record.isValidField('template_invoked'))
record.setValue('template_invoked', true);
// Prepare fields to reset
var templateData = this._getTemplateData(templateSysId);
var recordData = {};
// eslint-disable-next-line guard-for-in
for (var key in templateData) {
// Do not reset booleans, as they always have a value
var fieldElement = record.getElement(key);
if (!fieldElement || fieldElement.getED().getInternalType() == 'boolean')
continue;
if (record.getValue(key))
recordData[key] = record.getValue(key);
}
// Set assigned_to
var parentField = this._getLinkField(templateGr.getValue('link_element'), record);
var assignedToValue = this._getAssignedTo(templateGr, record, parentField);
if (assignedToValue)
record.setValue('assigned_to', assignedToValue);
var useAssignmentDate = this._getAssignmentDate(templateGr, record);
// Set use_assignment_date
if (useAssignmentDate) {
record.setValue('use_assignment_date', useAssignmentDate);
// Set offset fields
var offsetFields = this._getOffsetFields(templateGr, record);
if (offsetFields) {
record.setValue('date_offset_type', offsetFields.date_offset_type);
record.setValue('date_offset_units', offsetFields.date_offset_units);
record.setValue('date_offset_quantity', offsetFields.date_offset_quantity);
}
} else {
// Set due_date
var dueDate = this._getDueDate(templateGr, record, parentField);
if (dueDate && record.due_date !== null)
record.due_date.setDateNumericValue(dueDate);
}
// Apply template to record
var template = GlideTemplate.get(templateSysId);
template.setApplyChildren(false);
template.apply(record);
// Reset user input changes
if (!overwrite)
for (var field in recordData)
if (record.getValue(field) != recordData[field])
record.setValue(field, recordData[field]);
return record;
},
/* Apply the extensions of a template for a record (eg. children, siblings, template references)
* @param templateSysId : sys_id of the template to apply
* @param record : Optional GlideRecord the template was applied to
*/
applyAfter: function(templateSysId, record) {
var templateGr = new GlideRecord('sn_hr_core_template');
if (!templateGr.get(templateSysId) || !templateGr.active || !(record instanceof GlideRecord))
return;
var recordSysId = record.getUniqueValue();
this._appliedTemplates[templateSysId] = recordSysId;
// Adding checklist
var templateValue = templateGr.getValue('template');
if (!gs.nil(templateValue) && templateValue.includes('hr_task_type=checklist'))
this.applyChecklist(record);
// Apply children templates
if (templateGr.getValue('next_child'))
this._applyChildren(record.getRecordClassName(), recordSysId, templateGr.getValue('next_child'));
},
/* Apply a template to a record
* @param templateSysId : sys_id of the template to apply
* @param record : Optional GlideRecord to apply the template to
* @param postCatalogProcess : True if being called by catalog post processing
*/
apply: function(templateSysId, record, postCatalogProcess) {
// Setup template and record GlideRecords
var templateGr = new GlideRecord('sn_hr_core_template');
if (!templateGr.get(templateSysId) || !templateGr.active)
return;
if (!record)
record = new GlideRecord(templateGr.getValue('table'));
if (record.isValidField('template'))
record.setValue('template', templateSysId);
if (record.isValidField('template_invoked'))
record.setValue('template_invoked', true);
// Set assigned to
var parentField = this._getLinkField(templateGr.getValue('link_element'), record);
var assignedToValue = this._getAssignedTo(templateGr, record, parentField);
if (assignedToValue) {
/*If this is post-catalog insert, the parent has been changed
This means the assignment group must be voided to allow proper reassignment via the template */
var group = record.getValue('assignment_group');
if (postCatalogProcess && !gs.nil(group) && !new global.HRSecurityUtils().isMemberOfGroup(assignedToValue, group))
record.setValue('assignment_group', '');
record.setValue('assigned_to', assignedToValue);
}
// Set use_assignment_date
var useAssignmentDate = this._getAssignmentDate(templateGr, record);
if (useAssignmentDate) {
record.setValue('use_assignment_date', useAssignmentDate);
// Set offset fields
var offsetFields = this._getOffsetFields(templateGr, record);
if (offsetFields) {
record.setValue('date_offset_type', offsetFields.date_offset_type);
record.setValue('date_offset_units', offsetFields.date_offset_units);
record.setValue('date_offset_quantity', offsetFields.date_offset_quantity);
}
} else {
// Set due_date
var dueDate = this._getDueDate(templateGr, record, parentField);
if (dueDate && record.due_date !== null)
record.due_date.setDateNumericValue(dueDate);
}
// Apply template to record
var template = GlideTemplate.get(templateSysId);
template.setApplyChildren(false);
template.apply(record);
var recordUpdate = null;
if (record.isNewRecord())
recordUpdate = record.insert();
else
recordUpdate = record.update();
// At any point, if we are unable to insert into a parent table, do not try to insert into the descendant
// tables.
if (!recordUpdate)
return;
var recordSysId = record.getUniqueValue();
this._appliedTemplates[templateSysId] = recordSysId;
// Adding checklist
if (templateGr.getValue('template').includes('hr_task_type=checklist'))
this.applyChecklist(record);
// Apply children templates
if (templateGr.getValue('next_child'))
this._applyChildren(record.getRecordClassName(), recordSysId, templateGr.getValue('next_child'));
},
/* Apply the children templates
* @param parentTable : table name of the parent template created record
* @param parentSysId : sys_id of the parent template created record
* @param templateSysId : sys_id of the template to apply
* @param isFutureTask: boolean flag indicates if the record being applied is for future, in that case, do not
* create the record.
* @param grFuture: Gliderecord of sn_hr_le_future_todo table
*/
_applyChildren: function(parentTable, parentSysId, templateSysId, isFutureTask, grFuture) {
// Detect looping templates - Key could exist while value is empty string or null
if (this._appliedTemplates.hasOwnProperty(templateSysId))
return this._appliedTemplates[templateSysId];
// Add template sys_id to applied templates now to prevent circular dependencies in templates
this._appliedTemplates[templateSysId] = null;
// Setup template and record GlideRecords
var templateGr = new GlideRecord('sn_hr_core_template');
if (!templateGr.get(templateSysId))
return;
var record = new GlideRecord(templateGr.getValue('table'));
// If this is the template for the selected HR Service, prevent business rule from reapplying template
var templateHrServiceId = this._getTemplateProperty(templateSysId, 'hr_service');
if (templateHrServiceId) {
var serviceGr = new GlideRecord('sn_hr_core_service');
if (serviceGr.get(templateHrServiceId) && serviceGr.getValue('template') == templateSysId)
if (record.isValidField('template_invoked'))
record.setValue('template_invoked', true);
}
// Set parent
var parentField = this._getLinkField(templateGr.getValue('link_element'), record, parentTable);
if (parentField)
record.setValue(parentField, parentSysId);
// Set assigned to
var assignedToValue = this._getAssignedTo(templateGr, record, parentField);
if (assignedToValue)
record.setValue('assigned_to', assignedToValue);
// Set use_assignment_date
var useAssignmentDate = this._getAssignmentDate(templateGr, record);
if (useAssignmentDate) {
record.setValue('use_assignment_date', useAssignmentDate);
// Set offset fields
var offsetFields = this._getOffsetFields(templateGr, record);
if (offsetFields) {
record.setValue('date_offset_type', offsetFields.date_offset_type);
record.setValue('date_offset_units', offsetFields.date_offset_units);
record.setValue('date_offset_quantity', offsetFields.date_offset_quantity);
}
} else {
// Set due_date
var dueDate = this._getDueDate(templateGr, record, parentField);
if (dueDate && record.due_date !== null)
record.due_date.setDateNumericValue(dueDate);
}
// Apply template to record
var template = GlideTemplate.get(templateSysId);
template.setApplyChildren(false);
template.apply(record);
//set the template invoked, and template fields. Apply Template (after) BR will be triggered.
record.setValue('template_invoked', true);
record.setValue('template', templateSysId);
// Set template reference
if (templateGr.getValue('template_reference')) {
var referenceSysId = this._applyChildren(parentTable, parentSysId,
templateGr.getValue('template_reference'));
var templateReferenceGr = new GlideRecord('sn_hr_core_template');
templateReferenceGr.get(templateGr.getValue('template_reference'));
var templateReferenceField = this._getLinkField(templateGr.getValue('template_reference_field'), record,
templateReferenceGr.getValue('table'));
if (templateReferenceField)
record.setValue(templateReferenceField, referenceSysId);
}
var recordSysId = null;
if (isFutureTask) {
var futureJSON = {};
futureJSON.parent = String(record.getValue(parentField));
futureJSON.assigned_to_id = String(record.assigned_to);
futureJSON.assigned_to = String(record.getDisplayValue('assigned_to'));
futureJSON.assigned_to_display_name = String(record.getDisplayValue('assigned_to'));
futureJSON.short_description = String(new sn_hr_core.VariableReplacer().replaceFieldTokens(record.short_description,record));
futureJSON.future = true;
futureJSON.type = 'task';
futureJSON.sys_class_name = String(templateGr.table);
futureJSON.active = true;
futureJSON.number = 'NA';
// update the future task with the JSON.
if (!gs.nil(grFuture)) {
grFuture.future_json = new global.JSON().encode(futureJSON);
grFuture.short_description = futureJSON.short_description;
grFuture.assigned_to = futureJSON.assigned_to;
grFuture.table_name = futureJSON.sys_class_name;
grFuture.due_date = new GlideDateTime('2999-01-01 00:00:00');
grFuture.update();
}
} else {
recordSysId = record.insert();
this._appliedTemplates[templateSysId] = recordSysId;
}
// At any point, if we are unable to insert into a parent table, do not try to insert into the descendent
// tables.
if (recordSysId) {
// Apply sibling templates
if (templateGr.getValue('next'))
this._applyChildren(parentTable, parentSysId, templateGr.getValue('next'));
}
return recordSysId;
},
_getLinkField: function(linkField, recordGr, referenceTableName) {
if (recordGr.isValidField(linkField))
return linkField;
if (!referenceTableName || !recordGr)
return null;
var elements = recordGr.getElements();
for (var i = 0; i < elements.length; i++)
if (elements[i].getED().getInternalType() == 'reference' &&
new GlideTableHierarchy(elements[i].getReferenceTable()).getAllExtensions()
.indexOf(referenceTableName) != -1)
return elements[i].getName();
return null;
},
_getAssignedTo: function(templateGr, recordGr, parentField) {
var assignedToField;
// Prefer 'assign_to' field, but support legacy 'assigned_to_field'
if (templateGr.getValue('assign_to')) {
if (!parentField)
parentField = 'parent';
assignedToField = parentField + '.' + templateGr.getValue('assign_to');
} else if (templateGr.getValue('assigned_to_field'))
assignedToField = templateGr.getValue('assigned_to_field');
if (!assignedToField)
return null;
// Determine fields to dot walk
var fields = assignedToField.split('.');
if (!fields.length || !fields[0])
return null;
// Iterate over list of fields to dot walk
var assignedTo = recordGr[fields[0]];
if (!assignedTo)
return null;
for (var i = 1; i < fields.length; i++) {
assignedTo = assignedTo[fields[i]];
if (!assignedTo)
return null;
}
return assignedTo;
},
_getDueDate: function(templateGr, recordGr, parentField) {
var dueDateField;
if (templateGr.use_assignment_date)
return null;
if (templateGr.getValue('due_date_source')) {
if (!parentField)
parentField = 'parent';
dueDateField = parentField + '.' + templateGr.getValue('due_date_source');
}
if (!dueDateField)
return null;
// Determine fields to dot walk
var fields = dueDateField.split('.');
if (!fields.length || !fields[0])
return null;
// Iterate over list of fields to dot walk
var dueDate = recordGr[fields[0]];
if (!dueDate)
return null;
for (var i = 1; i < fields.length; i++) {
dueDate = dueDate[fields[i]];
if (!dueDate)
return null;
}
// Apply date offsets, if applicable
var dateOffsetType = templateGr.getValue('date_offset_type');
var dateOffsetUnits = templateGr.getValue('date_offset_units');
var dateOffsetQuantity = templateGr.getValue('date_offset_quantity');
return this._getCalculatedDueDate(dueDate, dateOffsetType, dateOffsetUnits, dateOffsetQuantity);
},
_getCalculatedDueDate: function(dueDate, dateOffsetType, dateOffsetUnits, dateOffsetQuantity) {
var gdt = new GlideDateTime();
gdt.setDisplayValue(dueDate.getDisplayValue());
if (dateOffsetType == 'on')
return gdt.getNumericValue();
var offsetSign = 0;
if (dateOffsetType == 'before')
offsetSign = -1;
else if (dateOffsetType == 'after')
offsetSign = 1;
else
return null;
var offsetTime = offsetSign * dateOffsetQuantity;
if (dateOffsetUnits == 'hours')
gdt.addSeconds(offsetTime * 3600);
else if (dateOffsetUnits == 'days')
gdt.addDaysLocalTime(offsetTime);
else if (dateOffsetUnits == 'weeks')
gdt.addWeeksLocalTime(offsetTime);
else if (dateOffsetUnits == 'months')
gdt.addMonthsLocalTime(offsetTime);
return gdt.getNumericValue();
},
_getTemplateData: function(templateSysId) {
var templateData = {};
var templateGr = new GlideRecord('sn_hr_core_template');
// validate if the template exists and active
if (templateGr.get(templateSysId) && templateGr.active && !gs.nil(templateGr.getValue('template'))) {
var templateFields = templateGr.getValue('template').split('^');
for (var i = 0; i < templateFields.length; i++) {
// Determine split to be first "=" to allow additional "="'s in field value
var splitIndex = templateFields[i].indexOf('=');
if (splitIndex > 0) {
var field = templateFields[i].substring(0, splitIndex);
var fieldValue = templateFields[i].substring(splitIndex + 1, templateFields[i].length);
templateData[field] = {
value: fieldValue,
displayValue: this._getTemplatesFieldDisplayValue(field, fieldValue, templateGr)
};
}
}
}
return templateData;
},
_getTemplatesFieldDisplayValue: function(field, value, templateGr) {
var templateForTable = String(templateGr.table);
return new hr_CoreUtils().getFieldsDisplayValue(field, value, templateForTable);
},
_getTemplateProperty: function(templateSysId, field) {
var templateGr = new GlideRecord('sn_hr_core_template');
if (templateGr.get(templateSysId) && templateGr.getValue('template')) {
var templateFields = templateGr.getValue('template').split('^');
for (var i = 0; i < templateFields.length; i++) {
// Determine split to be first "=" to allow additional "="'s in field value
var splitIndex = templateFields[i].indexOf('=');
// Check if this is desired field
if (splitIndex > 0 && templateFields[i].substring(0, splitIndex) == field)
return templateFields[i].substring(splitIndex + 1, templateFields[i].length); // return field value
}
}
return null;
},
/* Return array of active COE table names
*/
process: function() {
var tables = [];
var inactiveTables = gs.getProperty('sn_hr_core.inactive_tables', '').split(',');
// Add non-inactive sn_hr_core_case tables
var caseTables = hr.TABLE_CASE_EXTENSIONS;
for (var i = 0; i < caseTables.length; i++)
if (inactiveTables.indexOf(caseTables[i]) == -1)
tables.push(caseTables[i].toString());
// Add non-inactive sn_hr_core_task tables
var taskTables = hr.TABLE_TASK_EXTENSIONS;
for (i = 0; i < taskTables.length; i++)
if (inactiveTables.indexOf(taskTables[i]) == -1)
tables.push(taskTables[i].toString());
if (GlidePluginManager.isActive('com.snc.document_templates'))
tables.push('sn_doc_task');
var additionalTables = this.getAdditionalTables();
additionalTables.forEach(function(tableName){
if(tables.indexOf(tableName) > -1)
return;
tables.push(tableName);
});
return tables;
},
/*
Functionality: Calls extension point to add tables to the list of Task Table field in Activity Configuration Table
@return: array of tables
*/
getAdditionalTables: function() {
var tables=[];
if(GlidePluginManager.isActive('com.sn_hr_lifecycle_ent')){
try{
var eps = new GlideScriptedExtensionPoint().getExtensions("HRTemplateTableOptions");
eps.forEach(function(ep){
var additionalTables = ep.getAdditionalTables();
additionalTables.forEach(function(tableName){
if(tables.indexOf(tableName) > -1)
return;
var gr = new GlideRecord(tableName);
if(gr.isValid())
tables.push(tableName);
});
});
}
catch(ex){
gs.error("Adding additional table option failed for HR templates "+ ex.message);
}
}
return tables;
},
/*
* @parm record: Record to which checklist will be applied.
* @parm templateId: (optional) sys_id of the HR Template (eg. This is used for records without an hr_service field)
*
* Functionality: Applies a checklist to a record based on sn_hr_core_service or sn_hr_core_template.
*/
applyChecklist: function(record, templateId) {
// Table containing the reference to the checklist record
var checklistLinkTable = (record.getValue('hr_service')) ? 'sn_hr_core_service' : 'sn_hr_core_template';
// Field referencing the checklist record
var checklistLinkField = (record.getValue('hr_service')) ? 'hr_service' : 'template';
// sys_id of the record that references the checklist record
var checklistLinkSysId = templateId || record.getValue(checklistLinkField);
var checklistLinkTableGr = new GlideRecord(checklistLinkTable);
if (checklistLinkTableGr.get(checklistLinkSysId)) {
var cl = new GlideRecord('checklist');
cl.addQuery('table', checklistLinkTable);
cl.addQuery('document', checklistLinkSysId);
cl.query();
if (cl.next()) {
// Copy checklist and checklist items to record
var newCl = new GlideRecord('checklist');
newCl.setValue('table', record.getTableName());
newCl.setValue('document', record.getUniqueValue());
var checkListId = newCl.insert();
if (gs.nil(checkListId))
return;
var newClItem = new GlideRecord('checklist_item');
newClItem.addQuery('checklist', cl.getUniqueValue());
newClItem.orderBy('order');
newClItem.query();
while (newClItem.next()) {
newClItem.setValue('checklist', checkListId);
newClItem.insert();
}
}
}
},
_getAssignmentDate: function(templateGr, record) {
if (templateGr.table && templateGr.table == 'sn_hr_core_task')
return templateGr.use_assignment_date;
return null;
},
_getOffsetFields: function(templateGr, record) {
if (templateGr.table && templateGr.table == 'sn_hr_core_task')
return {
'date_offset_type': templateGr.date_offset_type,
'date_offset_units': templateGr.date_offset_units,
'date_offset_quantity': templateGr.date_offset_quantity
};
return null;
},
/* Apply a template to a record. This method is specifc to document task template
* @param templateSysId : sys_id of the document task template to apply
* @param record : Optional GlideRecord to apply the template to
* @return docTask: document task record
*/
applyDocumentTaskTemplate: function(templateSysId, record) {
var docTaskId;
var templateGr = new GlideRecord('sn_hr_core_template');
if (!templateGr.get(templateSysId) || !templateGr.active || templateGr.getValue('table')!='sn_doc_task')
return;
if (!record)
record = new GlideRecord('sn_doc_task');
// Apply template to record
var template = GlideTemplate.get(templateSysId);
template.setApplyChildren(false);
template.apply(record);
var dueDate;
if (templateGr.use_assignment_date) {
var currentDate = new GlideDateTime();
dueDate = this._getCalculatedDueDate(currentDate,templateGr.date_offset_type,
templateGr.date_offset_units,templateGr.date_offset_quantity);
} else
dueDate = this._getDueDate(templateGr, record);
if (!gs.nil(dueDate))
record.due_date.setDateNumericValue(dueDate);
return record;
},
/* Check whether the given table is one of the active HR Case Tables
* @param {String} tableName : Name of the table that we need to check
* @return {boolean}: Returns true if given table is one of the active HR Case Tables
*/
checkHRCaseTables: function(tableName) {
var inactiveTables = gs.getProperty('sn_hr_core.inactive_tables', '').split(',');
//Check non-inactive sn_hr_core_case tables
var caseTables = hr.TABLE_CASE_EXTENSIONS;
for (var i = 0; i < caseTables.length; i++)
if (inactiveTables.indexOf(caseTables[i]) == -1 && caseTables[i] == tableName)
return true;
return false;
},
/* Check whether the given table is one of the HR Task Tables
* @param {String} tableName : Name of the table that we need to check
* @return {boolean}: Returns true if given table is one of the HR Task Tables
*/
checkHRTaskTables: function(tableName) {
var taskTables = hr.TABLE_TASK_EXTENSIONS;
for(var i = 0; i < taskTables.length; i++)
if(taskTables[i] == tableName)
return true;
return false;
},
type: 'hr_TemplateUtils'
};
Sys ID
d9f16db02f321200b3c9a310c18c959e