Name
global.RowFieldQueryTerm
Description
This is used by the List s Show Matching/Filter Out context menu items Given inputs of table field_name sys_id oper Return a query term that represents a Show Matching or Filter Out query.
Script
var RowFieldQueryTerm = Class.create();
RowFieldQueryTerm.prototype = {
initialize : function() {
this.initialized = false;
},
process : function() {
var item = document.createElement("item");
item.setAttribute("term", this.getQueryTerm());
root.appendChild(item);
},
processQueryTerm : function(table, field, operator, sysId) {
this.table = table;
this.sys_id = sysId;
this.field = field;
this.oper = operator;
this.value = "";
this.initialized = true;
return this.getQueryTerm();
},
// Create a query term for table.field_name by getting the value from the
// record identified by sys_id
getQueryTerm : function() {
if (!this.initialized)
this._init();
// if the field is 'sys_id', is it as is
if (this.field == 'sys_id')
return 'sys_id' + this.oper + this.sys_id;
// Get the information about the field
var gr = this._getRecord();
if (gr == null)
return this.field + this.oper;
var fieldElement = gr.getElement(this.field);
if (fieldElement == null)
return this.field + this.oper;
var ed = fieldElement.getED();
var term = "";
this.value = this._getValue(gr, this.field);
this.fieldValue = this._getValue(gr, this.field);
if (ed.isEncrypted() || ed.isEdgeEncrypted())
term = this.field + this.oper + fieldElement.getDisplayValue();
// Show Matching/Filter Out on date/time type really means just the
// date, not date and time
var fieldValue = fieldElement.getValue();
if (ed.isDateType() &&
(fieldValue == null || (!ed.isEdgeEncrypted() && !ed.isEncrypted())))
term = this._getDateTimeTerm(gr, ed.isDateOnly());
//Show Matching/Filter Out on Phone Number E164.
if (ed.getInternalType() == "phone_number_e164" && ed.isEncrypted()) {
//phone number display value is not same as DB value after decryption
// Example:
// DisplayValue: +1 (415) 784-xxxx
// DB: +1415784xxxx
term = this.field + this.oper + fieldElement.getCLEDecryptedDBValue();
}
// Make sure choice list that has overridden label only queries within
// the specific table class
else if (ed.isChoiceTable())
term = this._getChoiceTerm(gr);
else if (ed.getInternalType() == "conditions")
this.value = this._escapeConditionsValue(this.value);
else if (ed.getInternalType() == "currency" || ed.getInternalType() == "price")
this.value = this._getCurrencyValue(fieldElement);
else if (ed.getInternalType() == "currency2")
term = this._getCurrency2Term(fieldElement);
else if (ed.getInternalType() == "translated_field")
this.value = this._getTranslatedValue(gr, this.field);
if (!this.value)
this.value = "NULL";
if (!term)
term = this.field + this.oper + this.value;
// NULL values should also be included for these non-boolean fields:
// a filter out on a non-zero scalar field
// a show matching on a zero-value scalar field
if (!ed.isBoolean()){
if (this._filterOutExplicitValue(ed) || this._showMatchingZero(ed))
term += "^OR" + this.field + "=NULL";
}
return term;
},
_escapeConditionsValue : function(val) {
return GlideStringUtil.escapeQueryTermSeparator(val);
},
_filterOutExplicitValue : function(ed) {
if (this.oper != "!=")
return false;
// price and currency have "0" for value if either zero or null
if (ed.getInternalType() == "price" || ed.getInternalType() == "currency")
return this.fieldValue != "0";
// if null is explicitly requested on a non-numeric, or zero on a choice, allow it to work.
if ((!ed.isTrulyNumber() || ed.isChoiceTable()) && this.value != "NULL")
return true;
return ((this.value != "NULL") && (this.value != "0"));
},
_showMatchingZero : function(ed) {
if (this.oper != "=")
return false;
// price and currency have "0" for value if either zero or null
if (ed.getInternalType() == "price" || ed.getInternalType() == "currency")
return (this.fieldValue == "0");
// don't apply to non-numeric or choice fields, since null and zero aren't
// equivalent.
if (!ed.isTrulyNumber() || ed.isChoiceTable())
return false;
return ((this.value == "NULL") || (this.value == "0"));
},
_init : function() {
this.table = request.getParameter('table');
this.sys_id = request.getParameter('sys_id');
this.field = request.getParameter('field_name');
this.oper = request.getParameter('oper');
this.value = "";
},
_getRecord : function() {
var gr = new GlideRecordSecure(this.table);
if (!gr.get(this.sys_id))
return null;
return gr;
},
_getValue : function(/* GlideRecord */gr, field) {
// to handle dot walked field names, we need to get the element and then
// get the value from the element
// GlideRecord.getValue does not work for dot walked fields
var e = gr.getElement(field);
if (!e && e != 0)
return null;
// DEF0292569: logic specific to choice fields - need to return null if empty but not if zero
var ed = e.getED();
if (ed.isChoiceTable() && !e && e.getValue() !== "0")
return null;
return e + '';
},
_getTranslatedValue: function( /* GlideRecord */ gr, field) {
return gr.getDisplayValue(field);
},
// Use date portion only for date/time fields
_getDateTimeTerm : function(/* GlideRecord */gr, /* boolean */isDateOnly) {
var ge = gr.getElement(this.field);
if (ge == null)
return null;
var gdt = ge.getGlideObject();
if (gdt == null)
return null;
// filter out or in on a null date
if (gdt.getDate() == null)
return null;
// If gdt is already a glide_date just get the value
var date = isDateOnly ? gdt.getValue() : gdt.getLocalDate().getValue();
var term = this.field;
if (this.oper == "=")
term += "ON";
else if (this.oper == ">" || this.oper == "<" || this.oper == ">=" || this.oper == "<=") {
term += this.oper;
this.useDateTime = true;
if (isDateOnly)
this.startEnd = this.oper == "<" || this.oper == ">=" ? "start" : "end";
} else
term += "NOTON";
if (this.useDateTime) {
if (isDateOnly)
term += "javascript:gs.dateGenerate('" + date + "','" + this.startEnd + "')";
else {
term += "javascript:gs.dateGenerate('" + date + "','" + gdt.getInternalFormattedLocalTime() + "')";
}
} else
term += date + "@javascript:gs.dateGenerate('" + date + "','start')@javascript:gs.dateGenerate('" + date + "','end')";
return term;
},
_getCurrencyValue: function(ge) {
return "javascript:global.getCurrencyFilter('" + this.table + "','" + this.field + "', '" +
ge.getSessionCurrencyCode() + ";" + this.value + "')";
},
/**
* Generally a match on a choice term is identical to a match on a non
* choice term. However, in the case of overloaded choice lists (where
* different child tables have different labels for the same choice values),
* we want to make sure we filter in/out the appropriate entries from the
* list by using the label along with the sys_class_name to do the filtering
*/
_getChoiceTerm : function(/* GlideRecord */gr) {
var tableName = gr.getRecordClassName();
var field = this.field + '';
var oc = new GlideOverLoadedChoices(tableName, field);
if (!oc.hasDups(this.value))
return null; // normal processing
var classes = oc.findPeerGroup(tableName, this.value);
if (!classes)
return null;
var setop = "IN";
var bridge = "^";
if (this.oper == "!=") {
setop = "NOT IN";
bridge = "^OR";
}
return this.field + this.oper + this.value + bridge + "sys_class_name" + setop + GlideStringUtil.join(classes);
},
_getCurrency2Term : function(fieldElement) {
// For both '=' and '!=' operators, there is no special query term. Comparison with the value which is
// NULL yields the correct results
if (!fieldElement.hasValue())
return;
var displayDigits = 0;
var displayValue = fieldElement.getDisplayValue().toString();
if (displayValue.includes('.')) {
displayDigits = displayValue.split('.')[1].trim().length;
}
var term;
// For other operators, get the bounds [lower, upper] such that the values in that range
// round to what is visible on screen
var roundedValue = this._round(fieldElement.amount, displayDigits);
var offset = Math.pow(10, -displayDigits) / 2;
var lowerBound = this._roundAndFormat(roundedValue - offset, displayDigits+1);
var upperBound = this._roundAndFormat(roundedValue + offset, displayDigits+1);
if (this.oper == '=') {
term = this.field + '>=' + fieldElement.currency + ',' + lowerBound
+ '^' + this.field + '<' + fieldElement.currency + ',' + upperBound;
} else if (this.oper == '!=') {
var code = fieldElement.currency.split(',')[0];
term = this.field + '<' + fieldElement.currency + ',' + lowerBound
+ '^OR' + this.field + '>=' + fieldElement.currency + ',' + upperBound
+ '^OR' + this.field + '.currency!=' + code;
}
return term;
},
_round : function(value, digits) {
return Number(Number(value).toFixed(digits));
},
_roundAndFormat : function(value, digits) {
return this._round(value, digits).toFixed(digits);
},
type : 'RowFieldQueryTerm'
};
Sys ID
ed91be3cc0a800660072f883f0c5b9ab