Map Field from Cart to Request

Megalithe
Tera Expert

I have a business requirement to add custom fields to the Service Portal cart. I've cloned the service portal widgets and added the necessary fields, but am having issues mapping the user inputs to the request when the checkout completes. 
*two-step checkout is enabled*

The widget is sc-shopping-cart-v2.

All of the documentation I have found is for prior versions using cart not cartjs. I just need one example of mapping a field to the new sc_request.

 

 

Server Script

(function() {
	var localInput = input; //to safeguard pullution of "input" via BR or other scripts
	//// TEST for Project % NYI
	data.table = {
		"list" : []
	};
	///
	
	data.engagement_channel = options.native_mobile ? 'mobile' : (options.isServiceWorkspace ? 'workspace' : 'sp');
	data.referrer = options.referrer;
	data.action = options.action;
	if (data.action)
		data.item = options.item;
	else
		data.action = 'checkout';
	
	if (localInput && localInput.action == "from_attachment")
		return;
	else if (localInput && localInput.action === 'log_request') {
		$sp.logStat('Order Now Request', localInput.itemDetails.sys_class_name, localInput.itemDetails.sys_id, localInput.itemDetails.name, $sp.getPortalRecord().getUniqueValue());
		$sp.logStat('Cat Item Request', localInput.itemDetails.sys_class_name, localInput.itemDetails.sys_id, localInput.itemDetails.name, $sp.getPortalRecord().getUniqueValue());
		return ;
	}

	var cartName = '';
	if (localInput)
		cartName = localInput.cart.name;
	else if (options.cart)
		cartName = options.cart.name;
	
	addInstrumentationData();
	
	var m = data.msgs = {};
	m.dialogTitle = gs.getMessage("Delete Attachment");
	m.dialogMessage = gs.getMessage("Are you sure?");
	m.dialogOK = gs.getMessage("OK");
	m.dialogCancel = gs.getMessage("Cancel");
	m.renameSuccessMsg = gs.getMessage("Attachment renamed successfully");
	m.deleteSuccessMsg = gs.getMessage("Attachment deleted successfully");
	m.delete_attachment = gs.getMessage("Delete Attachment?");
	m.requestSubmitted = gs.getMessage("Thank you, your request has been submitted.");
	m.checkingOutMsg = gs.getMessage("Submitting...");
	if (data.item.request_method == "request") {
		m.checkOutMsg = gs.getMessage("Request");
		m.checkoutPopupTitle = gs.getMessage("Request Confirmation");
	} else {
		m.checkOutMsg = gs.getMessage("Checkout");
		m.checkoutPopupTitle = gs.getMessage("Order Confirmation");
	}
	data.isMEE = options.native_mobile == 'true';
	data.sys_properties = {
		mobileNativeColor: gs.getProperty("glide.sc.mobile.primary_color", "#1f8476")
	};

	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} - please try again", "" + data.maxAttachmentSize + "MB");
	
	var cartJS;
	if (data.action !== 'order_now') {
		cartJS = new sn_sc.CartJS(cartName, '' + gs.getUser().getID());
		if (localInput && localInput.action === "change_shipping_info") {
			cartJS.setSpecialInstructions(localInput.special_instructions);
			cartJS.setRequestedFor(localInput.requestedFor);
			cartJS.setDeliveryAddress(localInput.deliverTo);
		}
	}
	
	if (localInput && localInput.action == 'order_guide') {
		var guideJS = new sn_sc.OrderGuide('' + cartName);
		cartJS = new sn_sc.CartJS('' + cartName);
		for(var i = 0; i < localInput.item.items.length; i++) {
			guideJS.navigateFromMap(localInput.item.items[i]);
		}
		cartJS.activateGuide();
		cartJS.setRequestedFor(localInput.requested_for);
		cartJS.setDeliveryAddress(localInput.delivery_address);
		cartJS.setSpecialInstructions(localInput.special_instructions);
		cartJS.setParentParams(localInput.parentParams);
		cartJS.setEngagementChannel(localInput.engagement_channel);
		cartJS.setReferrer(localInput.referrer);
		var request = cartJS.checkoutGuide();
		data.result = {sys_id: request.request_id, number: request.request_number || request.number, table: request.table || 'sc_request'};
		var portalId = $sp.getPortalRecord().getUniqueValue();
		$sp.logStat('Order Now Request', localInput.item.sys_class_name, localInput.item.sys_id, localInput.item.name, portalId);
		$sp.logStat('Cat Item Request', localInput.item.sys_class_name, localInput.item.sys_id, localInput.item.name, portalId);
		return;
	}
	
	if (localInput && localInput.action === 'checkout') {
		cartJS.setEngagementChannel(localInput.engagement_channel);
		checkoutCart(cartJS);
		return;
	}
	if (data.action !== 'order_now')
		
		data.cart = cartJS.getCartDetails(false);
	else {
		var requested_for = {
			user_id : gs.getUser().getID(),
			user_name: gs.getUser().getDisplayName()
		};
///test  values not coming over from Client 
	var procurementDetails;
		//logging
		console.log('server: =' + localInput.short_description);
		console.log('server: =' + localInput.organization);

		if (localInput && localInput.action === 'checkout') {
			procurementDetails.setShortDescription(localInput.short_description);
			procurementDetails.setDescription(localInput.description);
			procurementDetails.setOrganization(localInput.organization);
			procurementDetails.setOrganization(localInput.project);
			procurementDetails.setOrganization(localInput.justification);
			procurementDetails.setOrganization(localInput.account);
		}
		
///test

		data.cart = {
			name: cartName,
			sys_id: gs.generateGUID(),
			requested_for: requested_for.user_id,
			requested_for_display_name: requested_for.user_name,
			delivery_address: sn_sc.CartJS.getRequestedForAddress(requested_for.user_id)
			//test
			 
			//test
		};
	}
	
	if (options && options.parentParams) { //if parent is passed
			data.parentParams = options.parentParams;
	}
	if (options && options.requested_for && options.requested_for.id) { //If Passed via options
			data.cart.requested_for = options.requested_for.id;
			data.cart.requested_for_display_name = options.requested_for.displayValue;
			data.cart.delivery_address = sn_sc.CartJS.getRequestedForAddress(options.requested_for.id);
	}

	if (data.request_for) { //if value is changed by user
		var user = GlideUser.getUserByID(data.request_for);
		if (user.exists()) {
			data.cart.requested_for = data.request_for;
			data.cart.requested_for_display_name = user.getDisplayName();
			data.cart.delivery_address = sn_sc.CartJS.getRequestedForAddress(data.request_for);
		}
	}

	data.disable_req_for = sn_sc.CartJS.canViewRF();
	setRequestedForCols(data);
	data.reqForQuery = gs.getProperty("glide.sc.request_for.query");
	
})();

function setRequestedForCols(data) {
	var reqForDispCols = gs.getProperty("glide.sc.request_for.columns");
	if (JSUtil.notNil(reqForDispCols)) {
		data.reqForDispCol = "name";
		data.reqForDispCols = reqForDispCols.replace(/;/g, ",");
		data.reqForSearchCols = data.reqForDispCol + "," + data.reqForDispCols;
	}
	else {
		var displayCol = GlideTableDescriptor.get("sys_user").getDisplayName();
		data.reqForDispCol = displayCol || "name";
		data.reqForSearchCols = data.reqForDispCol;
		var refAcCols = GlideTableDescriptor.get("sys_user").getED().getAttribute("ref_ac_columns");
		if(JSUtil.notNil(refAcCols))
			data.reqForDispCols = (refAcCols + "").replace(/;/g, ",");

		var refAcSearch = GlideTableDescriptor.get("sys_user").getED().getAttribute("ref_ac_columns_search");
		if(JSUtil.notNil(data.reqForDispCols) && JSUtil.notNil(refAcSearch) && refAcSearch == "true")
			data.reqForSearchCols += "," + data.reqForDispCols;
	}
}

function checkoutCart(cart) {
		try {
				var cartItemGr = cart.getCartItems();
				data.numberOfCartItems = cartItemGr.getRowCount();
				var requestedCatItems = new global.GlobalServiceCatalogUtil().findCatItemsForSpLogs(cartItemGr);
				var request = cart.checkoutCart(true);
				data.result = {
						sys_id: request.request_id, 
						number: request.request_number, 
						table: 'sc_request',
						universal_request: request.universal_request
				};
				var portalId = $sp.getPortalRecord().getUniqueValue();
				$sp.logStat('Checkout Request', 'sc_request', request.request_id, request.request_number, portalId);
				new global.GlobalServiceCatalogUtil().logRequestedCatItems(requestedCatItems, portalId);
		} catch(e) {
				var catalogExceptionUtils = new CatalogExceptionUtils();
				if(catalogExceptionUtils.isCartException(e))
						gs.addErrorMessage(e.getMessage());
				data.numberOfCartItems = 0;
		}
}

function addInstrumentationData() {
	if (input && input.action == 'change_shipping_info')
		return;
	
	if (data.action == 'order_now') {
		var catSysId = data.item.sys_id;
		var gr = new GlideRecord('sc_cat_item');
		if (gr.get(catSysId))
			data.item.title = gr.getValue('name');
	} else if (input && input.cart && data.action == 'checkout') {
			var cartData = [];
			var _data;
			var cartSysId = input.cart.sys_id;
			var grCart = new GlideRecord('sc_cart_item');
			grCart.query("cart", cartSysId);
			while(grCart.next()){
				_data = {};
				var gr2 = new GlideRecord('sc_cat_item');
				if (gr2.get(grCart.getValue("cat_item"))) {
					_data.sys_id = gr2.getValue('sys_id');
					_data.title = gr2.getValue('name');
					_data.cartID = cartSysId;
					cartData.push(_data);
				}
			}
		data.cartData = cartData;
	}
}
1 REPLY 1

Mahesh23
Mega Sage

Hello,
Try below steps and see if it works for you

  1. Clone OOTB "SC Shopping Cart" widget.
    -Navigate to Service Portal > Widgets > search for SC Shopping Cart and Clone the widget.
  2. Create a copy of “large_shopping_cart_v2.html” Angular template to add new field.
    - Navigate to Service Portal > Widgets > search for SC Shopping Cart.

    - Go to Angular ng-templates related list & open “large_shopping_cart_v2.html”
     

  3. Rename the ID, change the Widget reference to new cloned widget created in Step 1, add new HTML code to include the new field & use Insert and Stay option to create a copy of “large_shopping_cart_v2.html”.
    Mahesh23_2-1694100798314.png- The ng-model="c.data.deliverTo" holds the user input entered in the field "Deliver to". The same value will be referenced by the Server Side script to update the Request record "Delivery address" field.

     


  4. Update the cloned "SC Shopping Cart" widget cart template default value to Angular template ID created in the above step as shown in the screenshot.
    Mahesh23_3-1694100931768.png
  5.  Update cloned "SC Shopping Cart" widget.
    - In line 33 the “input.deliveryTo” holds the value provided by the user in “Delivery to” field from the Service Portal, the same value is updated to Request record field "Delivery Address" by using Cart JS API setDeliveryAddress() method.

    Mahesh23_4-1694101035633.png
     If you have a requirement where you need to update value stored in the “deliveryTo” to other fields like Description follow below steps
  6. Create & store the user provided values in a variable and pass it to checkoutCart() function as a parameter as shown in the below image line 33 & 34.
    Mahesh23_5-1694101235093.png
  7. As soon as user clicks on “checkout” from the Cart the new Request record will be created and record details such as number, sys_id, table_name etc. will be stored in the data.result object, with the help of data.result perform GlideRecord() query against the newly created Request record to update the “Description” field with value stored in the “deliveryTo” variable as shown in the below image line 124 to 127.
    Mahesh23_6-1694101304569.png