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

_____
No AI was used in the writing of this post. Pure #GlideFather only

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