Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Create RITM through script in CSM scope

jainankit07
Tera Contributor

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:

createRitmFromCase: function(caseGr) {

        var catItem;

        var catSrch = new GlideRecord("sn_customerservice_case_itsm_decision");
        catSrch.addQuery("u_category", caseGr.category);
        catSrch.query();
        if (catSrch.next()) {
            catItem = catSrch.u_catalog_item;
        }

        var cart = new sn_sc.CartJS();
        var item = {
            'sysparm_id': catItem,
            'sysparm_quantity': '1',
            'variables': {
                'customer_name': caseGr.contact
            }
        };
gs.info("Testing, item created);
 
        var cartVals = cart.addToCart(item);
        var checkoutVals = cart.checkoutCart();
gs.info("Testing, RITM created);
          }
});

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.


1 ACCEPTED SOLUTION

MaxMixali
Kilo Sage

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.

View solution in original post

8 REPLIES 8

GlideFather
Tera Patron

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

_____
This reply is 100 % GlideFather and 0 % AI

Ankur Bawiskar
Tera Patron
Tera Patron

@jainankit07 

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! 🙏

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

@jainankit07 

so what was the solution and what was the issue?

please share so that it helps future members

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Hi @Ankur Bawiskar ,
I passed sys_id after converting to string, then it worked.

But I am facing a new challenge now.
The requirement was to create a case via record producer, and this case in turn will create RITM, but now, because of this n_sc.Cart() this record producer is creating 70-100 records. What should I do now?
Below is the latest code, which I thought is working fine

createRitmFromCase: function(caseGr) {

        var catItem;

        var catSrch = new GlideRecord("sn_customerservice_case_itsm_decision");
        catSrch.addQuery("u_category", caseGr.category);
        catSrch.query();
        if (catSrch.next()) {
            catItem = catSrch.u_catalog_item.toString();
        }
        var cart = new sn_sc.CartJS();
        var item = {
            'sysparm_id': catItem,
            'sysparm_quantity': '1',
            'variables': {
                'customer_name': caseGr.contact.toString(),
                'approving_data_steward': caseGr.u_approving_data_steward.toString(),
                'organization': caseGr.account.toString(),
                'u_organization_erp': caseGr.u_organization_erp.toString(),
                'category': caseGr.category.getValue(),
                'subcategory': caseGr.subcategory.getValue(),
                'u_priority': caseGr.u_priority.getValue(),
                'u_line_items_included': caseGr.u_line_items_included.getValue(),
                'u_impacted_organization_s': caseGr.u_impacted_organization_s.toString(),
                'notes': caseGr.short_description.getValue(),
                'u_department': caseGr.u_department.getValue()
            }
        };

        var cartVals = cart.addToCart(item);
        var checkoutVals = cart.checkoutCart();
 
 
 
Please assist.
There is some REST call I saw in transactions which is doing a lot of SQL queries and taking time.
The moment I disabled this code, it again began to create single Case record from producer