Name
global.ChangeModelChgReqAPISNC
Description
SNC Code for the ChangeModelChgReqAPI class. Implementation for the Change Request API for Change models.
Script
var ChangeModelChgReqAPISNC = Class.create();
ChangeModelChgReqAPISNC.prototype = {
CLOSE_CODE: {
SUCCESSFUL: "successful",
UNSUCCESSFUL: "unsuccessful",
SUCCESSFUL_ISSUES: "successful_issues"
},
LEGACY_CLOSE_STATE: (function(legacyStates) {
var closed = legacyStates.CLOSED;
var closedOther = legacyStates.CLOSED;
if (Array.isArray(legacyStates.CLOSED)) {
closed = legacyStates.CLOSED[0];
closedOther = legacyStates.CLOSED[1];
}
return {
SUCCESSFUL: closed,
UNSUCCESSFUL: closedOther,
SUCCESSFUL_ISSUES: closedOther
};
})(ChangeRequest.LEGACY_STATE || ChangeRequestSNC.LEGACY_STATE),
LEGACY_STATE: ChangeRequest.LEGACY_STATE || ChangeRequestSNC.LEGACY_STATE,
initialize: function (changeGr) {
this._gr = changeGr;
this._model = new ChangeModel(this._gr.chg_model.getRefRecord());
this.typeCompatibility = gs.getProperty(ChangeRequestSNC.TYPE_COMPATIBILITY, "false") === "true";
this.manageWorkflow = gs.getProperty(ChangeRequestSNC.MANAGE_WORKFLOW, "false") === "true";
this.plugin = {
"change_management": pm.isActive("com.snc.change_management"),
"foundation": pm.isActive("com.snc.change_management.foundation"),
"state_model": pm.isActive("com.snc.change_management.state_model"),
"change_model": pm.isActive("com.snc.change_management.change_model")
};
},
// New Model Methods
getStateFieldName: function () {
return this._model.getStateFieldName();
},
// Returns the initial state value of the model
getInitialState: function () {
var initialState = this._model.getFromCache("initial_state");
if (initialState !== null)
return initialState;
var stateGr = this._model.getInitialState();
if (!stateGr)
return null;
return stateGr.getValue("state_value");
},
// If the model is in an initial state. If not using models this will default to 'isNew'
isInitialState: function () {
return this._model.inInitialState(this._gr);
},
//Returns true if the Change Request changes to the initial state
changesToInitialState: function() {
return this._changesTo(this.getInitialState());
},
//Returns true if the Change Request changes from the initial state
changesFromInitialState: function() {
return this._changesFrom(this.getInitialState());
},
// Reverts the Change Request to the initial state
revertToInitialState: function () {
return this._model.applyInitialState(this._gr);
},
// If the change is in a terminal state (no transitions). If not using a model, is the sames as 'isClosed || isCancelled'.
isTerminalState: function () {
return this._model.inTerminalState(this._gr);
},
// Returns true if the state of the current record is the same as stateValue
// stateValue can be an sttrm_state record or a value
isState: function (stateValue) {
if (!stateValue)
return false;
if (this._isGlideRecord(stateValue)) {
if (this.getTableName() !== "sttrm_state")
return false;
stateValue = stateValue.getValue("state_value");
}
return stateValue === this._gr.getValue(this._model.getStateFieldName());
},
// Returns true if the current record has the provided state as an available next state
isNextState: function (stateValue) {
stateValue = stateValue + "";
var nextStates = this.getNextStates();
return nextStates.indexOf(stateValue) !== -1;
},
// Returns true if the provided state value is a valid manual state transition
isNextManualState: function(stateValue) {
stateValue = stateValue + "";
var nextStates = this.getNextManualStates();
return nextStates.indexOf(stateValue) !== -1;
},
getNextStates: function() {
var transitions = this._model.getFromCache("transitions") || {};
var currentState = this._gr.getValue(this.getStateFieldName());
if (transitions && transitions[currentState])
return transitions[currentState];
var stateValues = [];
var transitionStateGr = this._model.getTransitionStates(this._gr);
if (!transitionStateGr)
return stateValues;
while (transitionStateGr.next())
stateValues.push(transitionStateGr.getValue("state_value"));
transitions[currentState] = stateValues;
this._model.addToCache("transitions", transitions);
return stateValues;
},
getNextManualStates: function() {
var manualTransitions = this._model.getFromCache("manual_transitions") || {};
var currentState = this._gr.getValue(this.getStateFieldName());
if (manualTransitions && manualTransitions[currentState])
return manualTransitions[currentState];
var stateValues = [];
var transitionStateGr = this._model.getManualTransitionStates(this._gr);
if (!transitionStateGr)
return stateValues;
while (transitionStateGr.next())
stateValues.push(transitionStateGr.getValue("state_value"));
manualTransitions[currentState] = stateValues;
this._model.addToCache("manual_transitions", manualTransitions);
return stateValues;
},
moveTo: function (stateValue) {
if (!stateValue)
return false;
return this._model.applyState(this._gr, stateValue);
},
// Returns simple true/false values if the current record can transition to a new state
canMoveTo: function (stateValue) {
if (!stateValue)
return false;
return this.evaluateMoveTo(stateValue).transition_available;
},
// Returns the result of evaluating a move to the provided state
evaluateMoveTo: function(stateValue, returnAll) {
var noTransition = {
"from_state": this._gr.getValue(this.getStateFieldName()),
"to_state": stateValue,
"transition_available": false
};
if (!stateValue)
return returnAll ? [ noTransition ] : noTransition;
stateValue = stateValue + "";
var currentStateGr = this._model.getState(this._gr);
if (!currentStateGr)
return returnAll ? [ noTransition ] : noTransition;
var transitionStateGr = new STTRMState(currentStateGr).getTransition(stateValue);
if (!transitionStateGr)
return returnAll ? [ noTransition ] : noTransition;
var allTransition = [];
var unavailableTransition = null;
while (transitionStateGr.next()) {
var transition = new STTRMTransition(transitionStateGr).evaluateConditions(this._gr);
if (transition && transition.transition_available && !returnAll)
return transition;
if (unavailableTransition === null)
unavailableTransition = transition;
allTransition.push(transition);
}
if (returnAll)
return allTransition.length > 0 ? allTransition : [ noTransition ];
return unavailableTransition !== null ? unavailableTransition : noTransition;
},
// Returns true if the Change Request is in the defined 'implementation' state
canImplement: function() {
return this._model.getImplementationStates().indexOf(this._gr.getValue(this.getStateFieldName())) !== -1;
},
// Used to check multiple state values depending on the mapping of states to the is* etc. functions
_isStateMultiple: function (stateValues) {
if (Array.isArray(stateValues))
return stateValues.some(function (stateValue) {
return this.isState(stateValue);
}, this);
return this.isState(stateValues);
},
//Legacy state specific methods.
// Legacy new state methods
isNew: function () {
return this._isStateMultiple(this.LEGACY_STATE.NEW);
},
changesToNew: function () {
return this._changesTo(this.LEGACY_STATE.NEW);
},
changesFromNew: function () {
return this._changesFrom(this.LEGACY_STATE.NEW);
},
setNew: function () {
var stateVal = this.LEGACY_STATE.NEW;
return this.moveTo(Array.isArray(stateVal) ? stateVal[0] : stateVal);
},
toNew: function () {
return this.setNew() && !!this._gr.update();
},
// Legacy method. Use revertToInitialState instead with an update.
revertToNew: function () {
if (this.plugin.state_model && this.typeCompatibility) {
// Preserve the behaviour of types based change if installed
var previous = {};
previous.on_hold = this._gr.getValue("on_hold");
this.setValue('on_hold', false);
if (!this.revertToInitialState()) {
this._gr.setValue("on_hold", previous.on_hold);
return false;
}
if (this.manageWorkflow)
new ChangeTypeChgReqAPI(this._gr).deleteDefaultWorkflowContext();
return !!this._gr.update();
}
if (!this.revertToInitialState())
return false;
if (this.plugin.state_model && this.manageWorkflow)
new ChangeTypeChgReqAPI(this._gr).deleteDefaultWorkflowContext();
return !!this._gr.update();
},
// Legacy assess state methods. Use isState with a specific state value instead.
isAssess: function () {
return this._isStateMultiple(this.LEGACY_STATE.ASSESS);
},
changesToAssess: function () {
return this._changesTo(this.LEGACY_STATE.ASSESS);
},
setAssess: function () {
return this.moveTo(this.LEGACY_STATE.ASSESS);
},
assess: function () {
return this.setAssess() && !!this._gr.update();
},
// Legacy authorize state methods. Use isState with a specific state value instead.
isAuthorize: function () {
return this._isStateMultiple(this.LEGACY_STATE.AUTHORIZE);
},
changesToAuthorize: function () {
return this._changesTo(this.LEGACY_STATE.AUTHORIZE);
},
setAuthorize: function () {
return this.moveTo(this.LEGACY_STATE.AUTHORIZE);
},
authorize: function () {
return this.setAuthorize() && !!this._gr.update();
},
//Legacy scheduled state methods. Use isState with a specific state value instead.
isScheduled: function () {
return this._isStateMultiple(this.LEGACY_STATE.SCHEDULED);
},
changesToScheduled: function () {
return this._changesTo(this.LEGACY_STATE.SCHEDULED);
},
setScheduled: function () {
return this.moveTo(this.LEGACY_STATE.SCHEDULED);
},
scheduled: function () {
return this.setScheduled() && !!this._gr.update();
},
//Legacy implement state methods. Use isState with a specific state value instead.
isImplement: function () {
return this._isStateMultiple(this.LEGACY_STATE.IMPLEMENT);
},
changesToImplement: function () {
return this._changesTo(this.LEGACY_STATE.IMPLEMENT);
},
setImplement: function () {
return this.moveTo(this.LEGACY_STATE.IMPLEMENT);
},
implement: function () {
return this.setImplement() && !!this._gr.update();
},
//Legacy review state methods. Use isState with a specific state value instead.
isReview: function () {
return this._isStateMultiple(this.LEGACY_STATE.REVIEW);
},
changesToReview: function () {
return this._changesTo(this.LEGACY_STATE.REVIEW);
},
setReview: function () {
return this.moveTo(this.LEGACY_STATE.REVIEW);
},
review: function () {
this.setReview() && !!this._gr.update();
},
//Legacy close state methods. Use isState with a specific state value instead.
isClosed: function () {
return this._isStateMultiple(this.LEGACY_STATE.CLOSED);
},
changesToClosed: function () {
return this._changesTo(this.LEGACY_STATE.CLOSED);
},
// For isClosed*, No close_code field without change_management. All state driven.
isClosedSuccessful: function () {
if (!this.plugin.change_management)
return this.isState(this.LEGACY_CLOSE_STATE.SUCCESSFUL);
return this.isClosed() && this._gr.getValue("close_code") === this.CLOSE_CODE.SUCCESSFUL;
},
isClosedSuccessfulWithIssues: function () {
if (!this.plugin.change_management)
return this.isState(this.LEGACY_CLOSE_STATE.SUCCESSFUL_ISSUES);
return this.isClosed() && this._gr.getValue("close_code") === this.CLOSE_CODE.SUCCESSFUL_ISSUES;
},
isClosedUnsuccessful: function () {
if (!this.plugin.change_management)
return this.isState(this.LEGACY_CLOSE_STATE.UNSUCCESSFUL);
return this.isClosed() && this._gr.getValue("close_code") === this.CLOSE_CODE.UNSUCCESSFUL;
},
setClose: function (closeCode, closeNotes) {
var closeState = this.LEGACY_CLOSE_STATE.SUCCESSFUL;
var closeCodes = [
this.CLOSE_CODE.SUCCESSFUL,
this.CLOSE_CODE.SUCCESSFUL_ISSUES,
this.CLOSE_CODE.UNSUCCESSFUL
];
var legacyStates = [
this.LEGACY_CLOSE_STATE.SUCCESSFUL,
this.LEGACY_CLOSE_STATE.SUCCESSFUL_ISSUES,
this.LEGACY_CLOSE_STATE.UNSUCCESSFUL
];
var codeIdx = closeCodes.indexOf(closeCode);
if (codeIdx === -1)
codeIdx = 0;
if (!this.plugin.foundation && !this.plugin.state_model)
closeState = legacyStates[codeIdx];
var previous = {};
previous.close_notes = this._gr.getValue("close_notes");
if (closeNotes)
this._gr.setValue("close_notes", closeNotes);
if (this.plugin.change_management) {
previous.close_code = this._gr.getValue("close_code");
if (closeCode)
this._gr.setValue("close_code", closeCode);
}
// If we can apply the state, everything is OK
if (this._model.applyState(this._gr, closeState))
return true;
//Reset field values if we couldn't apply the state
this._gr.setValue("clode_notes", previous.close_notes);
if (this.plugin.change_management)
this._gr.setValue("close_code", previous.close_code);
return false;
},
close: function (closeCode, closeNotes) {
return this.setClose(closeCode, closeNotes) && !!this._gr.update();
},
closeSuccessful: function (closeNotes) {
return this.close(this.CLOSE_CODE.SUCCESSFUL, closeNotes ? closeNotes : gs.getMessage("Change closed successfully"));
},
closeSuccessfulWithIssues: function (closeNotes) {
return this.close(this.CLOSE_CODE.SUCCESSFUL_ISSUES, closeNotes ? closeNotes : gs.getMessage("Change closed successfully with issues"));
},
closeUnsuccessful: function (closeNotes) {
return this.close(this.CLOSE_CODE.UNSUCCESSFUL, closeNotes ? closeNotes : gs.getMessage("Change closed unsuccessfully"));
},
/**
* Cancel
*/
isCanceled: function () {
return this._isStateMultiple(this.LEGACY_STATE.CANCELED);
},
changesToCanceled: function () {
return this._changesTo(this.LEGACY_STATE.CANCELED);
},
setCancel: function () {
var stateVal = this.LEGACY_STATE.CANCELED;
return this.moveTo(Array.isArray(stateVal) ? stateVal[0] : stateVal);
},
cancel: function () {
return this.setCancel() && !!this._gr.update();
},
// Legacy requestApproval state transition methods
// This method assumes the Assess and Authorize states are used to create approvals,
// states which may not exist in the model
setRequestApproval: function() {
return (this.LEGACY_STATE.ASSESS && this.moveTo(this.LEGACY_STATE.ASSESS)) ||
(this.LEGACY_STATE.AUTHORIZE && this.moveTo(this.LEGACY_STATE.AUTHORIZE));
},
requestApproval: function() {
if (this.setRequestApproval())
return !!this._gr.update();
return false;
},
_changesTo: function (stateValue) {
if (!stateValue)
return false;
var stateFieldName = this._model.getStateFieldName();
if (Array.isArray(stateValue))
return stateValue.some(function (stateValue) {
return this._gr[stateFieldName].changesTo(stateValue);
}, this);
return this._gr[stateFieldName].changesTo(stateValue);
},
_changesFrom: function (stateValue) {
if (!stateValue)
return false;
var stateFieldName = this._model.getStateFieldName();
if (Array.isArray(stateValue))
return stateValue.some(function (stateValue) {
return this._gr[stateFieldName].changesFrom(stateValue);
}, this);
return this._gr[stateFieldName].changesFrom(stateValue);
},
_isGlideRecord: function (inputVar) {
return inputVar && typeof inputVar.getTableName === "function";
},
type: 'ChangeModelChgReqAPISNC'
};
ChangeModelChgReqAPISNC.newNormal = function () {
var NORMAL_MODEL = "007c4001c343101035ae3f52c1d3aeb2";
return ChangeModelChgReqAPI.newChange(NORMAL_MODEL);
};
ChangeModelChgReqAPISNC.newStandard = function () {
var STANDARD_MODEL = "e55d0bfec343101035ae3f52c1d3ae49";
return ChangeModelChgReqAPI.newChange(STANDARD_MODEL);
};
ChangeModelChgReqAPISNC.newEmergency = function () {
var EMERGENCY_MODEL = "62d10fa1c303101035ae3f52c1d3aec1";
return ChangeModelChgReqAPI.newChange(EMERGENCY_MODEL);
};
ChangeModelChgReqAPISNC.newChange = function (modelSysIdOrType) {
// Allow type names for backwards compatibility
var namedTypes = {};
namedTypes[ChangeRequest.NORMAL] = ChangeModelChgReqAPI.newNormal;
namedTypes[ChangeRequest.STANDARD] = ChangeModelChgReqAPI.newStandard;
namedTypes[ChangeRequest.EMERGENCY] = ChangeModelChgReqAPI.newEmergency;
if (modelSysIdOrType && namedTypes[modelSysIdOrType])
return namedTypes[modelSysIdOrType]();
var changeGr = new GlideRecord("change_request");
changeGr.newRecord();
//If a model sysId isn't provided try the default from the change request record
var changeModelGr = null;
if (!modelSysIdOrType) {
if (changeGr.chg_model.nil())
return null;
changeModelGr = changeGr.chg_model.getRefRecord();
} else {
changeModelGr = new GlideRecord("chg_model");
if (!changeModelGr.get(modelSysIdOrType))
return null;
}
var changeModel = new ChangeModel(changeModelGr);
changeModel.applyModel(changeGr);
return new ChangeRequest(changeGr);
};
Sys ID
0f41f8eb5303101034d1ddeeff7b12fd