Name

sn_sow_chg.SOWChgScheduleAssistSNC

Description

No description available

Script

var SOWChgScheduleAssistSNC = Class.create();
SOWChgScheduleAssistSNC.prototype = {

  PLUGIN_CONFLICT_DETECTION: 'com.snc.change.collision',

  initialize: function(tableName, sysId, startDate, endDate, beginningOfWeekMS) {
  	this._log = new global.GSLog('com.snc.uib.sow_change.schedule_assistant.log', this.type).setLog4J();

  	this.tableName = tableName || "change_request";
  	var changeGr = new GlideRecordSecure(this.tableName);
  	this.tableNameValid = changeGr.isValid();

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[initialize] tableNameValid: " + this.tableNameValid);

  	this.changeExists = false;
  	if (this.tableNameValid && changeGr.get(sysId)) {
  		this.sysId = sysId;
  		this.changeExists = true;
  		this.changeGr = changeGr;
  	}

  	if (this._log.atLevel(global.GSLog.DEBUG))
  		this._log.debug("[initialize] changeExists: " + this.changeExists);

  	this.startEndPresent = this._initStartEnd(startDate, endDate);
  	if (!this.startEndPresent) {
  		if (this._log.atLevel(global.GSLog.ERROR))
  			this._log.error("[initialize] Provide a StartDate and EndDate");

  		return;
  	}

  	this.startEndValid = this._isDateTimeValid(this.proposedStartDate) && this._isDateTimeValid(this.proposedEndDate);
  	if (!this.startEndValid) {
  		if (this._log.atLevel(global.GSLog.ERROR))
  			this._log.error("[initialize] Provide a valid StartDate and EndDate");

  		return;
  	}

  	this.duration = GlideDateTime.subtract(this.proposedStartDate, this.proposedEndDate);

  	if (beginningOfWeekMS && beginningOfWeekMS[0] !== '' && beginningOfWeekMS[0] !== 'null') {
  		if (isNaN(parseInt(beginningOfWeekMS[0])) || parseInt(beginningOfWeekMS[0]) <= 0) {
  			if (this._log.atLevel(global.GSLog.ERROR))
  				this._log.error("[initialize] Please provide a valid beginningOfWeekMS value " + beginningOfWeekMS);

  			return;
  		}

  		this._updateStartEndWithContext(beginningOfWeekMS);
  	}

  	if (this.proposedStartDate.after(this.proposedEndDate)) {
  		if (this._log.atLevel(global.GSLog.ERROR))
  			this._log.error("[initialize] Ensure startDate: " + startDate + " is before endDate: " + endDate);

  		return;
  	}

  	var currentDateTime = new GlideDateTime();
  	currentDateTime.setDisplayValue(currentDateTime.getDisplayValue());
  	if (currentDateTime.after(this.proposedStartDate))
  		this._updateStartEndWithCurrentDate(currentDateTime);
  },
  
  _initStartEnd: function(startDate, endDate) {
  	if ((startDate && startDate[0] !== 'null' && startDate[0] !== '') || (endDate && endDate[0] !== 'null' && endDate[0] !== '')) {
  		this.proposedStartDate = this._setDisplay(startDate);
  		this.proposedEndDate = this._setDisplay(endDate);
  		return true;
  	} else if (this.changeExists && this.changeGr.getValue('start_date') && this.changeGr.getValue('end_date')) {
  		this.proposedStartDate = new GlideDateTime();
  		this.proposedStartDate.setValue(this.changeGr.getValue('start_date'));
  		this.proposedEndDate = new GlideDateTime();
  		this.proposedEndDate.setValue(this.changeGr.getValue('end_date'));
  		return true;
  	}
  	return false;
  },

  _updateStartEndWithContext: function(beginningOfWeekMS) {
  	if (!beginningOfWeekMS || beginningOfWeekMS === 'null' || beginningOfWeekMS === '')
  		return;

  	this.proposedStartDate = new GlideDateTime();
  	this.proposedStartDate.setNumericValue(beginningOfWeekMS);
  	this.proposedEndDate = new GlideDateTime(this.proposedStartDate);
  	this.proposedEndDate.add(this.duration.getNumericValue());
  },

  _updateStartEndWithCurrentDate: function(currentDateTime) {
  	this.proposedStartDate = new GlideDateTime();
  	this.proposedStartDate.setDisplayValue(currentDateTime.getDisplayValue());
  	currentDateTime.add(this.duration.getNumericValue());
  	this.proposedEndDate = currentDateTime;
  },

  getScheduleAssistConfig: function() {
  	var result = {};
  	result.title = gs.getMessage("Scheduling Assistant");
  	result.timeSlots = this.getAvailabilityConfig();
  	result.range = this.getRange(result.timeSlots.timeSlotArr);
  	result.message = this.getMessageObj(result.timeSlots.timeSlotArr, result.range);
  	result.dateTimeFormat = this.getDateTimeFormat();
  	result.timeZone = this.getSystemTimeZone();
  	result.locale = this.getUserLocale();
  	result.firstDayOfWeek = this.getFirstDayOfWeek();
  	result.selectedDate = this.getSelectedDate(result.timeSlots.timeSlotArr);
  	result.nextAvailableSlot = this.getNextAvailableSlot(result.timeSlots.timeSlotArr[0]);
  	return result;
  },

  getScheduleAssistCardDetails: function() {
  	var cardDetails = {};
  	cardDetails.messages = {
  		"label": gs.getMessage("Earliest without conflicts"),
  		"noConflictsTag": gs.getMessage("no conflicts")
  	};
  	var timeSlots = this.getAvailabilityConfig();
  	cardDetails.nextAvailableSlot = this.getNextAvailableSlot(timeSlots.timeSlotArr[0]);

  	cardDetails.startAndEnd = "";

  	if (!timeSlots.timeSlotArr.length) {
  		var range = this.getRange(timeSlots.timeSlotArr);
  		var messageObj = this.getMessageObj(timeSlots.timeSlotArr, range);
  		cardDetails.errorMessage = messageObj.reasonMsg;
  		return cardDetails;
  	}

  	durationDisplayValue = [this._getFormattedDate(cardDetails.nextAvailableSlot.start_display_value),
  		this._getFormattedTime(cardDetails.nextAvailableSlot.start_display_value),
  		this._getFormattedDate(cardDetails.nextAvailableSlot.end_display_value),
  		this._getFormattedTime(cardDetails.nextAvailableSlot.end_display_value)];
  	
  	if (durationDisplayValue.length >= 2) {
  		if (durationDisplayValue[0] === durationDisplayValue[2])
  			cardDetails.startAndEnd = gs.getMessage("{0} {1} to {3}", durationDisplayValue);
  		else
  			cardDetails.startAndEnd = gs.getMessage("{0} {1} to {2} {3}", durationDisplayValue);
  	}

  	cardDetails.fields = {
  		start_date: this._getFieldLabel("start_date"),
  		end_date: this._getFieldLabel("end_date")
  	};

  	return cardDetails;
  },

  getDateTimeFormat: function() {
  	var dateTimeConfigFormat = {
  		"dateFormat": gs.getDateFormat(),
  		"timeFormat": gs.getTimeFormat(),
  		"dateTimeFormat": gs.getDateTimeFormat()
  	};
  	return dateTimeConfigFormat;
  },

  getSystemTimeZone: function() {
  	return gs.getSession().getTimeZoneName();
  },

  getUserLocale: function() {
  	return gs.getSession().getLanguage();
  },

  getFirstDayOfWeek: function() {
  	var gdt = new GlideDateTime(gs.beginningOfThisWeek());
  	return gdt.getDayOfWeekLocalTime();
  },

  getSelectedDate: function(timeSlotArr) {
  	if (!timeSlotArr || timeSlotArr.length === 0)
  		return "";

  	var gdt = new GlideDateTime(timeSlotArr[0].start_value);
  	var selectedDateObj = gdt.getDate();
  	return selectedDateObj.getDisplayValue();
  },

  getNextAvailableSlot: function(timeSlotArr) {
  	if (!timeSlotArr)
  		return {};

  	nextAvailableSlotObj = {};
  	nextAvailableSlotObj.start = timeSlotArr.start;
  	nextAvailableSlotObj.end = timeSlotArr.end;
  	nextAvailableSlotObj.type = timeSlotArr.type;
  	nextAvailableSlotObj.start_value = timeSlotArr.start_value;
  	nextAvailableSlotObj.start_display_value = timeSlotArr.start_display_value;
  	nextAvailableSlotObj.end_value = timeSlotArr.end_value;
  	nextAvailableSlotObj.end_display_value = timeSlotArr.end_display_value;
  	return nextAvailableSlotObj;
  },

  getAvailabilityConfig: function() {
  	var availabilityObj = {
  		timeSlotArr: []
  	};

  	if (!this.tableNameValid || !this.changeExists || !this.startEndPresent || !this.startEndValid || this.proposedStartDate.after(this.proposedEndDate))
  		return availabilityObj;

  	var chgAvailabilityObj = {};
  	if (GlidePluginManager.isActive(this.PLUGIN_CONFLICT_DETECTION))
  		chgAvailabilityObj = new global.ChangeConflictSchedule(this.changeGr, this.proposedStartDate, this.proposedEndDate).findScheduleWindows();


  	for (var i = 0; i < chgAvailabilityObj.spans.length; i++) {
  		availabilityObj.timeSlotArr[i] = {
  			"start": new GlideDateTime(chgAvailabilityObj.spans[i].start.value).getDisplayValueInternal(),
  			"end": new GlideDateTime(chgAvailabilityObj.spans[i].end.value).getDisplayValueInternal(),
  			"type": "available",
  			"start_value": chgAvailabilityObj.spans[i].start.value,
  			"start_display_value": chgAvailabilityObj.spans[i].start.display_value,
  			"end_value": chgAvailabilityObj.spans[i].end.value,
  			"end_display_value": chgAvailabilityObj.spans[i].end.display_value
  		};
  	}

  	return availabilityObj;
  },

  getRange: function(timeSlots) {
  	var suggestedRange = {
  		searchWindow: "",
  		rangeStartDate: "",
  		rangeEndDate: "",
  		nextStartDate: "",
  		nextEndDate: ""
  	};

  	if (timeSlots.length != 0) 
  		return suggestedRange;

  	if (!this.tableNameValid || !this.changeExists || !this.startEndPresent || !this.startEndValid || this.proposedStartDate.after(this.proposedEndDate))
  		return suggestedRange;

  	var scheduleWindow = gs.getProperty("change.conflict.next_available.schedule_window", "180");
  	var intScheduleWindow = parseInt(scheduleWindow, 10);
  	// 7 days is the smallest window of time used to search for the next available time
  	if (intScheduleWindow < 7) {
  		intScheduleWindow = 7;
  		scheduleWindow = "7";
  	// 1000 days is the largest window of time used to search for the next available time
  	} else if (intScheduleWindow > 1000) {
  		intScheduleWindow = 1000;
  		scheduleWindow = "1000";
  	}

  	suggestedRange.searchWindow = scheduleWindow;

  	var gdtRangeStartDate = this._setDisplay(this.proposedStartDate.getDisplayValue());
  	var gdtRangeEndDate = this._setDisplay(this.proposedStartDate.getDisplayValue());
  	var gdtNextEndDate = this._setDisplay(this.proposedEndDate.getDisplayValue());

  	gdtRangeStartDate.addDaysUTC(intScheduleWindow);
  	suggestedRange.rangeStartDate = this._getFormattedDate(gdtRangeStartDate) + "";

  	gdtRangeEndDate.addDaysUTC(2 * intScheduleWindow);
  	suggestedRange.rangeEndDate = this._getFormattedDate(gdtRangeEndDate) + "";

  	suggestedRange.nextStartDate = gdtRangeStartDate.getDisplayValue() + "";

  	gdtNextEndDate.addDaysUTC(intScheduleWindow);
  	suggestedRange.nextEndDate = gdtNextEndDate.getDisplayValue() + "";

  	return suggestedRange;
  },

  getMessageObj: function(timeSlotArr, range) {
  	var messageObj = {
  		headerMsg: "",
  		introMsg: "",
  		reasonMsg: "",
  		reviewMsg: "",
  		searchAvailable: false
  	};

  	if (timeSlotArr.length != 0)
  		return messageObj;

  	messageObj.headerMsg = "No Availability Found";

  	if (!this.tableNameValid) {
  		messageObj.reasonMsg = gs.getMessage("Reason: Provide a valid table name");
  		messageObj.searchAvailable = false;
  		return messageObj;
  	}

  	if (!this.changeExists) {
  		messageObj.reasonMsg = gs.getMessage("Reason: Provide a valid sysId");
  		messageObj.searchAvailable = false;
  		return messageObj;
  	}

  	if (!this.startEndPresent) {
  		messageObj.reasonMsg = gs.getMessage("Reason: Define a start and end date in your record");
  		messageObj.searchAvailable = false;
  		return messageObj;
  	}

  	if (!this.startEndValid) {
  		messageObj.reasonMsg = gs.getMessage("Reason: Provide a valid start and end date");
  		messageObj.searchAvailable = false;
  		return messageObj;
  	}

  	if (this.proposedStartDate.after(this.proposedEndDate)) {
  		messageObj.reasonMsg = gs.getMessage("Reason: Ensure that start date is before the end date");
  		messageObj.searchAvailable = false;
  		return messageObj;
  	}

  	var chgAvailabilityObj = {};
  	if (GlidePluginManager.isActive(this.PLUGIN_CONFLICT_DETECTION))
  		chgAvailabilityObj = new global.ChangeConflictSchedule(this.changeGr, this.proposedStartDate, this.proposedEndDate).findScheduleWindows();

  	var formattedStartDate = new GlideDate();
  	var gdtRangeStartDate = new GlideDate();

  	gdtRangeStartDate.setDisplayValue(this.proposedStartDate.getDisplayValue());
  	formattedStartDate = this._getFormattedDate(gdtRangeStartDate);

  	var msgArr = [range.rangeStartDate, range.rangeEndDate, formattedStartDate, range.searchWindow];

  	messageObj.headerMsg = gs.getMessage("No availability found");
  	messageObj.introMsg = gs.getMessage("There is no availability for {3} days from {2}", msgArr);
  	messageObj.reasonMsg = chgAvailabilityObj.message;
  	messageObj.reviewMsg = gs.getMessage("Review change request conflicts or search for availability between {0} and {1}", msgArr);
  	messageObj.searchAvailable = true;

  	return messageObj;
  },

  _getFieldLabel: function(field) {
  	var gr = new GlideRecord(this.tableName);
  	return gr.getElement(field).getLabel();
  },

  _setDisplay: function(dateTimeValue) {
  	var dateTime = new GlideDateTime();
  	if (isNaN(dateTimeValue))
  		dateTime.setDisplayValue(dateTimeValue);
  	else
  		dateTime.setNumericValue(dateTimeValue);
  	return dateTime;
  },

  _isDateTimeValid: function(glideDateTime) {
  	return glideDateTime && typeof glideDateTime.isValid === "function" && glideDateTime.isValid();
  },

  _getFormattedDate: function(value) {
  	var gd = new GlideDate();
  	gd.setValue(value);
  	return gd.getByFormat("MMMM d, y");
  },

  _getFormattedTime: function(value) {
  	var gt = new GlideTime();
  	gt.setValue(value);
  	return gt.getByFormat("hh:mm a");
  },

  type: 'SOWChgScheduleAssistSNC'
};

Sys ID

e41d36e8771011101ee2d9d28a5a99bb

Offical Documentation

Official Docs: