- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-10-2019 10:09 AM
Hi all, I've seen several posts about this but looking for the right solution. I have a client that is not using the shopping cart in their Service Portal for their end users...in other words every REQ only has one RITM. And to keep is simple, we want to only expose the RITMs to the end users...that way they don't have to know the difference, and they don't have to click on the REQ to then have to click on the RITM, etc. So how can I configure the catalog item submit so that when the end user submits the form, they are redirected to the newly created RITM? I'm using the "SC Catalog Item Deprecated" widget, because with this goal of just showing RITMs, it appears to be a better UX. thanks!
Solved! Go to Solution.
- Labels:
-
Service Portal Development

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-11-2019 08:01 AM
Okay Patrick,
I've cloned the SC Catalog Item Deprecated widget and edited the Client Controller and Server Script. Before the redirect in the Client Controller I've put a check to see if the table is "sc_request", if so, I'm passing in the Sys Id of the request to the Input object in the Server script. When the Server Script gets that input, it will do a GlideRecord query to see if there is exactly ONE RITM associated to that request. If there is, it will send back that RITM's sys_id to the Client Controller and the redirect will be built to go to the ticket page with that RITM.
This is what I've got working:
Server Script
// populate the 'data' variable with catalog item, variables, and variable view
(function() {
// portal can specify a catalog and catalog category home page
data.sc_catalog_page = $sp.getDisplayValue("sc_catalog_page") || "sc_home";
data.sc_category_page = $sp.getDisplayValue("sc_category_page") || "sc_category";
options.show_add_cart_button = (options.show_add_cart_button == "true");
if (options.page) {
var pageGR = new GlideRecord("sp_page");
options.page = (pageGR.get(options.page)) ? pageGR.getValue("id") : null;
}
if (options.table) {
var tableGR = new GlideRecord("sys_db_object");
options.table = (tableGR.get(options.table)) ? tableGR.getValue("name") : null;
}
options.url = options.url || "?id={page}&table={table}&sys_id={sys_id}";
data.showPrices = $sp.showCatalogPrices();
var m = data.msgs = {};
m.serviceCatalogMsg = gs.getMessage("Service Catalog");
m.submitMsg = gs.getMessage("Submit");
m.submittedMsg = gs.getMessage("Submitted");
m.createdMsg = gs.getMessage("Created");
m.trackMsg = gs.getMessage("track using 'Requests' in the header or");
m.clickMsg = gs.getMessage("click here to view");
m.dialogTitle = gs.getMessage("Delete Attachment");
m.dialogMessage = gs.getMessage("Are you sure?");
m.dialogOK = gs.getMessage("OK");
m.dialogCancel = gs.getMessage("Cancel");
data.maxAttachmentSize = parseInt(gs.getProperty("com.glide.attachment.max_size", 1024));
if (isNaN(data.maxAttachmentSize))
data.maxAttachmentSize = 24;
m.largeAttachmentMsg = gs.getMessage("Attached files must be smaller than {0} MB - please try again", "" + data.maxAttachmentSize);
m.renameSuccessMsg = gs.getMessage("Attachment renamed successfully");
m.deleteSuccessMsg = gs.getMessage("Attachment deleted successfully");
if (input){
data.sys_id = input.sys_id;
//Input REQ sys id from the Client Controller
if(input.requestId){
//Search for related RITMs
var ritm = new GlideRecord('sc_req_item');
ritm.addQuery('request',input.requestId);
ritm.query();
//If exactly one RITM is returned, pass to the Client Controller to redirect user
if(ritm.next() && (ritm.getRowCount() == 1)){
data.ritmId = ritm.getUniqueValue();
}
}
}else if (options.sys_id)
data.sys_id = options.sys_id;
else
data.sys_id = $sp.getParameter("sys_id") || $sp.getParameter('sl_sys_id');
if (!data.sys_id)
return;
data._attachmentGUID = gs.generateGUID();
var validatedItem = new sn_sc.CatItem('' + data.sys_id);
if (!validatedItem.canView() || !validatedItem.isVisibleServicePortal())
return;
data.sc_cat_item = $sp.getCatalogItem({
sys_id: data.sys_id + '',
is_ordering: true
});
if (data.sc_cat_item.category) {
var categoryJS = new sn_sc.CatCategory(data.sc_cat_item.category);
data.category = {
name: categoryJS.getTitle(),
url: '?id='+data.sc_category_page+'&sys_id=' + data.sc_cat_item.category
};
data.categories = [];
data.categories.push({
label: categoryJS.getTitle(),
url: '?id='+data.sc_category_page+'&sys_id=' + data.sc_cat_item.category
});
while(categoryJS && categoryJS.getParent()) {
var parentId = categoryJS.getParent();
categoryJS = new sn_sc.CatCategory(parentId);
var category = {
label: categoryJS.getTitle(),
url: '?id='+data.sc_category_page+'&sys_id=' + parentId
};
data.categories.unshift(category);
}
}
$sp.logStat('Catalog View', data.sc_cat_item.sys_class_name, data.sys_id, data.sc_cat_item.name);
data.msgs.delete_attachment = gs.getMessage("Delete Attachment?");
})();
Client Controller
function ($scope, $http, spUtil, nowAttachmentHandler, $rootScope, $sanitize, $window, $sce, i18n, $timeout, $log, spAriaUtil, $location, spModal) {
var c = this;
c.quantity = 1;
if ($scope.data.sc_cat_item)
$scope.data.sc_cat_item.description = $sce.trustAsHtml($scope.data.sc_cat_item.description);
c.widget._debugContextMenu = [
[ i18n.getMessage("Open") + " sc_cat_item", function(){
var item = c.data.sc_cat_item;
$window.open("/sp_config?id=form&table=" + item.table + "&sys_id=" + item.sys_id); }]
];
c.showAddCartBtn = function() {
return c.options.show_add_cart_button &&
c.data.sc_cat_item.sys_class_name !== "sc_cat_item_producer" &&
!c.data.sc_cat_item.no_cart;
}
c.showQuantitySelector = function() {
return c.data.sc_cat_item.sys_class_name !== "sc_cat_item_producer" &&
!c.data.sc_cat_item.no_quantity &&
(!c.data.sc_cat_item.no_order_now || !c.data.sc_cat_item.no_cart);
}
c.showOrderNowButton = function() {
return c.data.sc_cat_item.use_sc_layout || !c.data.sc_cat_item.no_order_now;
}
c.allowOrder = function() {
if (c.data.sc_cat_item.use_sc_layout)
return true;
if (c.data.sc_cat_item.no_order)
return false;
if (c.data.sc_cat_item.no_order_now && c.data.sc_cat_item.no_cart)
return false;
return true;
}
$scope.$on('dialog.upload_too_large.show', function(e){
$log.error($scope.m.largeAttachmentMsg);
spUtil.addErrorMessage($scope.m.largeAttachmentMsg);
});
$scope.m = $scope.data.msgs;
$scope.submitButtonMsg = $scope.m.submitMsg;
var ah = $scope.attachmentHandler = new nowAttachmentHandler(setAttachments, appendError);
function appendError(error) {
spUtil.addErrorMessage(error.msg + error.fileName);
}
ah.setParams('sp_portal', $scope.data._attachmentGUID, 1024 * 1024 * $scope.data.maxAttachmentSize);
function setAttachments(attachments, action) {
$scope.attachments = attachments;
if (action === "added")
$scope.setFocusToAttachment();
if (action === "renamed")
spAriaUtil.sendLiveMessage($scope.m.renameSuccessMsg);
if (action === "deleted")
spAriaUtil.sendLiveMessage($scope.m.deleteSuccessMsg);
}
$scope.attachmentHandler.getAttachmentList();
$scope.confirmDeleteAttachment = function(attachment) {
spModal.confirm($scope.data.msgs.delete_attachment).then(function() {
$scope.attachmentHandler.deleteAttachment(attachment);
$scope.setFocusToAttachmentButton();
});
}
// Breadcrumbs
if ($scope.data.sc_cat_item) {
if (!$scope.data.categories)
$scope.data.categories = [];
$scope.data.categories.unshift({label: $scope.data.msgs.serviceCatalogMsg, url: '?id=' + $scope.data.sc_catalog_page});
$scope.data.categories.push({label: $scope.data.sc_cat_item.name, url: '#'});
$timeout(function() {
$scope.$emit('sp.update.breadcrumbs', $scope.data.categories);
});
spUtil.setSearchPage('sc');
} else {
var notFoundBC = [{label: $scope.data.msgs.serviceCatalogMsg, url: '?id=' + $scope.data.sc_catalog_page}];
$timeout(function() {
$scope.$emit('sp.update.breadcrumbs', notFoundBC);
});
spUtil.setSearchPage('sc');
}
c.getItemId = function () {
return $scope.data.sc_cat_item ? $scope.data.sc_cat_item.sys_id : -1;
};
var g_form;
$scope.$on('spModel.gForm.initialized', function(e, gFormInstance){
if (gFormInstance.getSysId() != -1 && gFormInstance.getSysId() != c.getItemId())
return;
g_form = gFormInstance;
// This runs after all onSubmit scripts have executed
g_form.$private.events.on('submitted', function(){
if ($scope.data.sc_cat_item.item_action === "order")
getOne();
else if ($scope.data.sc_cat_item.item_action === "add_to_cart")
addToCart();
});
});
$scope.triggerAddToCart = function() {
$scope.data.sc_cat_item.item_action = "add_to_cart";
$scope.data.sc_cat_item.quantity = c.quantity;
if (g_form)
g_form.submit();
}
$scope.triggerOnSubmit = function(){
$scope.data.sc_cat_item.item_action = "order";
$scope.data.sc_cat_item.quantity = c.quantity;
if (g_form)
g_form.submit();
}
// order / create request
function getOne() {
postCatalogFormRequest().success(function(response) {
var a = response.result ? response.result : response.answer;
var n = a.number;
$scope.$emit("$$uiNotification", response.$$uiNotification ? response.$$uiNotification : a.$$uiNotification);
$scope.$emit("$sp.sc_cat_item.submitted", a);
if (n)
issueMessage(n, a.table, a.sys_id, a.redirect_to, a.redirect_portal_url);
$scope.submitting = false;
$scope.submitButtonMsg = $scope.m.submittedMsg;
}).error(function(response) {
console.log(response);
});
}
function addToCart() {
postCatalogFormRequest().success(function(response) {
$rootScope.$broadcast("$sp.service_catalog.cart.add_item");
$rootScope.$broadcast("$sp.service_catalog.cart.update");
//spUtil.addInfoMessage("Added item to shopping cart");
$scope.submitting = false;
c.status = "Added item to shopping cart";
});
}
function postCatalogFormRequest() {
setFieldsReadonly();
$scope.submitted = true;
$scope.submitting = true;
var requestUrl;
var reqData = {};
if ($scope.data.sc_cat_item.sys_class_name === "sc_cat_item_producer") {
requestUrl = '/api/sn_sc/v1/servicecatalog/items/' + $scope.data.sc_cat_item.sys_id + '/submit_producer';
for(var obj in $scope.data.sc_cat_item._fields)
reqData[$scope.data.sc_cat_item._fields[obj].name] = $scope.data.sc_cat_item._fields[obj].value;
reqData = {'variables' : reqData, 'attachment_id' : $scope.data._attachmentGUID, 'attachment_table': 'sp_portal', 'get_portal_messages': 'true'};
}
else {
requestUrl = spUtil.getURL('sc_cat_item');
reqData = $scope.data.sc_cat_item;
reqData._attachmentGUID = $scope.data._attachmentGUID;
}
return $http.post(requestUrl, reqData);
}
// spModel populates mandatory - hasMandatory is called by the submit button
$scope.hasMandatory = function(mandatory) {
return mandatory && mandatory.length > 0;
};
// switch catalog items
var unregister = $scope.$on('$sp.list.click', onListClick);
$scope.$on("$destroy", function() {
unregister();
});
function onListClick(evt, arg) {
$scope.data.sys_id = arg.sys_id;
spUtil.update($scope);
}
function setFieldsReadonly(){
var allFields = g_form.getFieldNames();
for(var fieldName in allFields){
g_form.setReadOnly(allFields[fieldName], true);
}
}
function issueMessage(n, table, sys_id, redirectTo, redirectUrl) {
var page = table == 'sc_request' ? 'sc_request' : 'ticket';
if (c.options.page) {page = c.options.page;}
if (c.options.table) {table = c.options.table;}
if (redirectTo == 'catalog_home') page = 'sc_home';
if(table == 'sc_request'){
//If table is sc_request, pass the Sys Id of the REQ to the data object in the server and update
c.data.requestId = sys_id;
c.server.update().then(function(){
//Wait for server to update so that Client Controller data object updates
//If exactly one RITM sys id is returned, then direct user to the Ticket page of that RITM
if(c.data.ritmId){
table = 'sc_req_item';
sys_id = c.data.ritmId;
page = 'ticket';
var url = spUtil.format(c.options.url, {page: page, table: table, sys_id: sys_id});
if (c.options.auto_redirect == "true") {
$timeout(function() {
if (redirectUrl)
$location.url(redirectUrl);
else
$location.url(url);
}, 1000);
return;
}
}
});
}else{
//If table is not sc_request, such as a Record Producer, use Out of the Box process
var url = spUtil.format(c.options.url, {page: page, table: table, sys_id: sys_id});
if (c.options.auto_redirect == "true") {
$timeout(function() {
if (redirectUrl)
$location.url(redirectUrl);
else
$location.url(url);
}, 1000);
return;
}
var t = $scope.m.createdMsg + " " + n + " - ";
t += $scope.m.trackMsg;
t += ' <a href="' + url + '">' + $scope.m.clickMsg + '</a>';
spUtil.addInfoMessage(t);
}
}
}
Also, make sure the only option filled out on the Instance Options is Auto-redirect
Let me know if that works for you. I've added inline comments to hopefully further illustrate how I made this happen. Make sure to thoroughly test all of this with both Catalog Items and Record producers, and verify it redirects to the correct page.
If my answer was helpful or answered your question, please mark it as 'Helpful' or 'Correct'
Thanks!
Josh

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-10-2019 10:10 AM
Something like this.
action.setRedirectURL(current);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-10-2019 10:15 AM
Hi Alexander,
is that for a record producer? I need this to work for catalog items creating REQs and RITMs...would that apply here too?

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-10-2019 10:12 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-10-2019 10:14 AM
Hi Harshvardhan, that link is not working
(?)