- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thursday
I have a requirement where I need to create a RITM on insert of a Case.
I have a Business Rule which in turn is calling a script include
and script include has below code:
BR is calling the function and infact first part of the code is also working fine where I am gliding a table to get the sys_id of catalog item.
It's the new sn_sc.CartJS API which seems to be creating issue.
I am getting the log till - gs.info("Testing, item created);
I am not getting last log.
If somebody has previously done this or knows how to do it, please assist.
Solved! Go to Solution.
- Labels:
-
Request Management
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Friday
ServiceNow – Create RITM on Case Insert using sn_sc.CartJS (Working Pattern)
Your symptoms
- You see the log “Testing, item created” but not “Testing, RITM created”.
- The CartJS step is likely erroring out (and your gs.info lines also have syntax issues).
Top 8 pitfalls that usually break CartJS from a Business Rule / Script Include
1) Syntax errors in logs
- You have missing closing quotes: gs.info("Testing, item created); and gs.info("Testing, RITM created);
2) Wrong execution context
- CartJS executes as the current session user. If your BR is async/system, it may lack catalog access or requester context. Prefer AFTER INSERT, synchronous.
3) Missing catalog item or wrong sys_id type
- Ensure catItem is a string (sys_id), not a GlideElement. Use catItem = String(catSrch.getValue('u_catalog_item'));
4) Variables must use the **internal variable names**
- E.g., 'customer_name' must match the variable Name on the catalog item (not the label).
5) Required variables not provided
- If the item has mandatory variables, CartJS will fail. Provide all required ones or default them.
6) Requested for / cart user context
- If needed, set 'sysparm_requested_for' and/or impersonate the case contact user when creating the cart.
7) Use try/catch and check return objects
- CartJS returns objects with IDs; log them and handle failures.
😎 Scope / API availability
- Ensure plugin com.glideapp.servicecatalog and API sn_sc.CartJS are accessible in your scope. If not, use GlideRecord insert on sc_cart_item + sc_req_item via sn_sc.CartJS only.
Recommended, robust pattern
- Business Rule (Table: sn_customerservice_case) – When: after insert – Condition: your criteria – Calls Script Include function.
- Script Include (server-side, not client-callable).
Sample Script Include function (drop-in)
---------------------------------------
createRitmFromCase: function(caseGr) {
// 0) Guard: find catalog item
var catId = '';
var catSrch = new GlideRecord('sn_customerservice_case_itsm_decision');
catSrch.addQuery('u_category', caseGr.getValue('category'));
catSrch.query();
if (catSrch.next()) {
catId = String(catSrch.getValue('u_catalog_item'));
}
if (!catId) {
gs.error('RITM create: No catalog item found for category=' + caseGr.getDisplayValue('category'));
return null;
}
try {
gs.info('RITM create: building cart for case ' + caseGr.getValue('number') + ', catItem=' + catId);
// 1) Prepare item payload
var vars = {
// Use variable INTERNAL NAMES here:
'customer_name': caseGr.getDisplayValue('contact') || caseGr.getValue('contact'),
// add other required vars...
};
var item = {
'sysparm_id': catId,
'sysparm_quantity': '1',
'variables': vars,
// optionally set who it's for:
'sysparm_requested_for': caseGr.getValue('opened_for') || gs.getUserID()
};
// 2) Create cart and add item
var cart = new sn_sc.CartJS();
var addRes = cart.addToCart(item);
// addRes may include 'sys_id' of sc_cart_item and 'cart_id'
gs.info('RITM create: addToCart result = ' + new global.JSON().encode(addRes));
// 3) Checkout / place order
var orderRes = cart.checkoutCart(); // places the order for current user context
gs.info('RITM create: checkout result = ' + new global.JSON().encode(orderRes));
// orderRes typically includes: number, request_id (REQ), ritm_ids (array)
if (orderRes && orderRes.ritm_ids && orderRes.ritm_ids.length > 0) {
gs.info('RITM create: created RITMs = ' + orderRes.ritm_ids.join(','));
// Optionally relate Case↔RITM:
try {
var ritmGR = new GlideRecord('sc_req_item');
if (ritmGR.get(orderRes.ritm_ids[0])) {
// e.g., make a related record
caseGr.u_ritm = ritmGR.getUniqueValue(); // if you have a field to store the link
caseGr.update();
}
} catch (e2) {
gs.warn('RITM create: could not link case to RITM: ' + e2.message);
}
return orderRes;
} else {
gs.error('RITM create: checkout returned no RITM IDs');
return null;
}
} catch (e) {
gs.error('RITM create: exception: ' + e.message);
return null;
}
}
Key notes
- Fix your logging lines (close quotes).
- Ensure the BR runs AFTER INSERT and not async for the first pass. If you must run async, confirm the user context has catalog access.
- If you need the RITM to be created as the Case’s contact or opened_for, consider impersonating for the operation:
```js
var sess = gs.getSession();
var original = gs.getUserID();
if (caseGr.opened_for) sess.impersonate(caseGr.opened_for);
// run CartJS here
sess.impersonate(original); // restore
```
- If checkoutCart() is blocked by required variables, supply them all or set defaults at the item level.
Minimal fix to your original snippet
------------------------------------
- Close the quotes on gs.info lines.
- Convert u_catalog_item to string sys_id and verify variable names.
Example:
var catItem = String(catSrch.getValue('u_catalog_item'));
var cart = new sn_sc.CartJS();
var item = {
'sysparm_id': catItem,
'sysparm_quantity': '1',
'variables': {
'customer_name': caseGr.getDisplayValue('contact')
}
};
gs.info('Testing, item created');
var cartVals = cart.addToCart(item);
var checkoutVals = cart.checkoutCart();
gs.info('Testing, RITM created');
Troubleshooting checklist
- Confirm catItem sys_id exists and is Active.
- Confirm the current execution user has permission to order that item.
- Check if the item requires additional variables (UI Policy/mandatory).
- Use System Logs → All to capture CartJS errors (they are server-side).
- Temporarily wrap with try/catch and gs.error(e.message) for visibility.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thursday
Hi @jainankit07,
your script doesn't contain the creation part..
a simple draft example could be:
var demoGR = new GlideRecord('target_table'); //sc_req_item
demoGR.initialize(); //to start the insertion
demoGR.field_nameOne = "Assign your value here";
demoGR.field_nameTwo = "Assign your value here";
demoGR.insert(); //end the insertion
Let me know what do you think about this
/* If my response wasn’t a total disaster ↙️ ⭐ drop a Kudos or Accept as Solution ✅ ↘️ Cheers! */
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Friday
do you have 2 step checkout in your instance?
possibly it's failing because of that
Did you print what's the error in logs?
💡 If my response helped, please mark it as correct ✅ and close the thread 🔒— this helps future readers find the solution faster! 🙏
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Friday
so what was the solution and what was the issue?
please share so that it helps future members
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Friday
ServiceNow – Create a RITM on Case insert (use server-side Cart API, not CartJS)
Problem
You’re calling sn_sc.CartJS() from a Business Rule / Script Include to create a RITM when a Case is inserted. You see the first gs.info but not the final one. Root causes:
1) CartJS is a client-side (portal) facade; in server-side code use sn_sc.Cart().
2) Minor syntax issue in your sample (missing closing quotes in gs.info lines).
3) Variable values must be passed as strings/sys_ids appropriate to the variable type.
Correct approach (server-side)
Use the server-side Cart API: sn_sc.Cart(). This creates REQ/RITM in one transaction.
When to run
- Business Rule on sn_customerservice_case (or your case table)
- When: AFTER INSERT (or AFTER INSERT/UPDATE with guard conditions)
- Synchronous or Async? Prefer Async for external calls; for straight creation, After Insert is fine.
Script Include function (drop-in)
---------------------------------
createRitmFromCase: function(caseGr) {
// 1) Resolve catalog item by your mapping table
var catItemId = '';
var catSrch = new GlideRecord('sn_customerservice_case_itsm_decision');
catSrch.addQuery('u_category', caseGr.getValue('category'));
catSrch.setLimit(1);
catSrch.query();
if (catSrch.next()) {
catItemId = catSrch.getValue('u_catalog_item'); // sc_cat_item.sys_id
}
if (!catItemId) {
gs.warn('No catalog item mapping found for category=' + caseGr.getDisplayValue('category'));
return;
}
// 2) Build variable hash (keys must be variable "Name" values on the cat item)
var vars = {};
// Example variable "customer_name" expects a reference to sys_user or a string (adjust to your variable type)
// If it is a reference to sys_user and caseGr.contact is a reference, pass sys_id:
vars.customer_name = caseGr.getValue('contact'); // sys_id
// Add more variables as needed, e.g.:
// vars.case_number = caseGr.getValue('number');
// vars.case_short_description = caseGr.getValue('short_description');
gs.info('Creating RITM from Case ' + caseGr.getDisplayValue('number') + ' for item ' + catItemId);
// 3) Create item under a new Request (Cart API always creates a new REQ)
var cart = new sn_sc.Cart();
var itemSysId = cart.addItem(catItemId, 1, vars);
// (Optional) set Requested For / special fields by updating the RITM before checkout
// var ritm = new GlideRecord('sc_req_item');
// if (ritm.get(itemSysId)) {
// ritm.requested_for = caseGr.getValue('contact') || caseGr.getValue('opened_by');
// ritm.short_description = 'Auto-created for Case ' + caseGr.getValue('number');
// ritm.update();
// }
var reqSysId = cart.placeOrder();
gs.info('RITM created from Case ' + caseGr.getValue('number') + ' → REQ=' + reqSysId + ', RITM item_sys_id=' + itemSysId);
}
Business Rule (After Insert on Case)
------------------------------------
Table: sn_customerservice_case (or your extension)
When: after insert
Filter condition: (category IS NOT EMPTY) AND (whatever your business condition is)
Script:
(function executeRule(current, previous /*null when async*/) {
try {
new x_your_scope.YourUtils().createRitmFromCase(current);
} catch (e) {
gs.error('Failed to create RITM from Case ' + current.getValue('number') + ': ' + e);
}
})(current, previous);
Important details & tips
------------------------
1) Use sn_sc.Cart() (server-side). CartJS is for client/portal via GlideAjax.
2) Variable keys must match the variable “Name” on the target catalog item (not the label).
3) Pass correct value types:
- Reference variable → pass sys_id string
- Choice variable → pass the underlying value (not display)
- Checkbox → 'true'/'false' (string) or true/false (boolean)
- Date/Time → GlideDateTime-compatible string
4) User permissions: the executing user must have rights to order that item. In BR context, the system runs as that session user. If needed, wrap in gs.getSession().impersonate('some_user') or use GlideSystem elevated privileges (with caution).
5) Availability: ensure the sc_cat_item is Active, visible to the user, and in an orderable catalog/category.
6) If you must attach the new RITM to an existing REQ (e.g., one REQ per Case), the Cart API cannot do that; you’d have to create sc_req_item yourself and populate variable rows (sc_item_option_mtom). Cart always creates a new REQ on checkout.
7) Logging: ensure gs.info lines have closing quotes (your sample had syntax errors):
gs.info('Testing, item created');
gs.info('Testing, RITM created');
Troubleshooting checklist
-------------------------
- Error in system logs about “CartJS” or missing class → switch to sn_sc.Cart().
- No RITM created: check item availability & user permissions; verify mapping table returns a valid cat item sys_id.
- Variables blank: ensure variable names match and values are valid types; verify in sc_item_option_mtom after order.
- Multiple items per case: call cart.addItem repeatedly before cart.placeOrder() to create a single REQ with multiple RITMs.
TL;DR
-----
Don’t use CartJS on the server. Use the server-side **sn_sc.Cart()** to add the item + variables and **placeOrder()**. Ensure variable names/values match your catalog item definitions and that the executing context has permission to order the item.
