The CreatorCon Call for Content is officially open! Get started here.

Multiple RITMs under 1 REQ

phugill
Tera Expert

 

Hi Community,

I’m trying to figure out the best way to create multiple Requested Items (RITMs) from a single Catalog Item submission.

Use case:

  • We have one catalog item with several checkboxes. (It Systems, Information Security, Finance)

  • When the form is submitted, I want a separate RITM created for each selected checkbox.

  • Each RITM should contain the same variable values, but be assigned to a different group depending on which checkbox was selected.

  • All RITMs should roll up under the same REQ, and ideally be displayed on their own tabs within the request.

What I’ve tried so far:

  • Order Guides → but we want this to happen without extra clicks or navigating to multiple screens.

  • Cart APIs → I’ve tested a few approaches but haven’t been able to get them working for this use case (maybe I’m not setting them up correctly).

  • Workflow → I have a workflow triggered when the catalog item is submitted that checks each checkbox, but I don’t know how to branch it into separate RITMs.

  • Custom Action → I tried adding a custom action, but it doesn’t seem to show up as an option when I go to use it.

Has anyone successfully implemented this pattern before? My main focus is to drive this through Flow Designer. We have not implemented multiple RITMs in our environment before. 

Any best practices, code samples, or pointers would be hugely appreciated.

Thanks

Philip H

1 ACCEPTED SOLUTION

phugill
Tera Expert

I wanted to share the solution I was able to build in Flow Designer without using any custom actions or scripting.

I started with a Service Catalog trigger, then used Get Catalog Variables to retrieve the specific variables I needed.

phugill_0-1759507980165.png

To associate multiple RITMs with the REQ, I added a Look Up Record on the sc_request table to retrieve the Sys ID of the parent request.

phugill_1-1759508021050.png

From there, I applied If / Else If conditions based on the catalog variable checkboxes:

  • If IT Systems is true → update the primary Request Item record.

  • If Finance is true → create a Request Item record.

  • If Information Security is true → create a Request Item record.

phugill_2-1759508057912.png

For the Else If conditions:

  • If Information Security is true and IT Systems is false → update the primary Request Item.

  • If Finance is true → create a Request Item record.

phugill_3-1759508107225.png

For the final Else condition:

  • If IT Systems is false and Finance is true → update the primary Request Item.

  • If Information Security is true → create a new Request Item record.

phugill_4-1759508146854.png

Finally, I used an Update Request Record step.

phugill_5-1759508177379.png

The tricky part was ensuring that updates to the REQ didn’t wipe out values when non-primary RITMs were being updated (since the primary has the flow context attached to it). My workaround was to use the Look Up Trigger Service Catalog Request Item record to pull values from there.

phugill_6-1759508220882.png

Attempting to populate the REQ directly from the catalog variables would cause errors, but pulling them from the trigger record worked reliably.

 

I hope this helps!

 

 

View solution in original post

13 REPLIES 13

Ankur,

 

Thank You for your response. 

Yes, I have been working on following what you have put together but have been having troubles getting it implemented correctly. I'm not familiar with JSON and how to utilize it effectively in the environment. Your article is not entirely clear.

@phugill 

I believe I have explained it very well.

what did you start and share the script and please tell where are you stuck?

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

Ankur, 

Below is what I'm currently doing but running into a block to add the Action to my flow. 

In BackGround Scripts I ran this to test my theory. 

var params = {
    it_systems: true,
    infosec: false,
    finance: true,
    requested_for: 'b6912e76dbf37600cd073220ad9619b8',  // sys_id of a user
    requested_by: gs.getUserID(),                        // current user sys_id
    u_vendor_name: 'Sample Vendor',
    u_evaluation_type: 'Standard',
    due_date: '2025-10-01',
    short_description: 'Testing',
};

var reqNumber = new MultiRitmCreator().createRitms(params);
gs.info("Created Request Number: " + reqNumber);Action in flow designer

Here is my Script Include

var MultiRitmCreator = Class.create();
MultiRitmCreator.prototype = {
    initialize: function() {
    },

    createRitms: function(params) {
        try {
            var catalogItem = 'c3278427fb2f22104a3dfbd14eefdcc8'; // your catalog item sys_id

            // Build options based on checkbox inputs
            var options = [];
            if (params.it_systems)
                options.push({group: '52d931d9dbb8cb00cd073220ad961930', value: 'IT Systems'});
            if (params.infosec)
                options.push({group: '5abb260bdb2cc700cd073220ad961997', value: 'Information Security'});
            if (params.finance)
                options.push({group: 'b528f51c8754c65010e0ca65dabb3511', value: 'Finance'});

            if (!options.length)
                throw "No areas selected (it_systems, infosec, finance).";

            var cartId = GlideGuid.generate(null);
            var cart = new Cart(cartId);

            for (var i = 0; i < options.length; i++) {
                var item = cart.addItem(catalogItem, 1);

                // Set catalog variables
                cart.setVariable(item, 'requested_for', params.requested_for);
                cart.setVariable(item, 'requested_by', params.requested_by);
                cart.setVariable(item, 'u_vendor_name', params.u_vendor_name);
                cart.setVariable(item, 'u_evaluation_type', params.u_evaluation_type);
                cart.setVariable(item, 'due_date', params.due_date);
                cart.setVariable(item, 'selected_area', options[i].value);

            }

            var rc = cart.placeOrder();
            return rc.number;

        } catch (e) {
            gs.error("MultiRitmCreator error: " + e);
            return null;
        }
    },

    type: 'MultiRitmCreator'
};

My Flow designer Action

phugill_0-1757998847393.png

Action Script

(function execute(inputs, outputs) {
    try {
        // Build params for the Script Include from action inputs
        var params = {
            it_systems: !!inputs.it_systems,
            infosec: !!inputs.infosec,
            finance: !!inputs.finance,
            requested_for: inputs.requested_for,       // pass sys_id (Reference) or string
        };

        // Call the Script Include
        var creator = new MultiRitmCreator();
        var reqNumber = creator.createRitms(params);

        outputs.requestNumber = reqNumber;
    } catch (ex) {
        gs.error("Action Create Multiple RITMs error: " + ex);
        outputs.requestNumber = '';
    }
})(inputs, outputs);

Output

phugill_1-1757998901853.png

When I go to my flow it does not show up. I am in global scope and this is all built in global. 

phugill_2-1757998955205.png

For your Solution I am unclear where to add the script you included. Is that a catalog script? Script Include?

Manikandan Than
Tera Expert

Hello @phugill ,

You can handle this in Flow Designer without using Order Guides.

  • Create a Flow with trigger “After Requested Item Created” for your catalog item.

  • Pass in the REQ, RITM, Catalog Item, and the checkbox variables.

  • Build a simple map of checkboxes → assignment group sys_ids.

  • In a Run Script step, loop through the selected checkboxes:

    • Use req.addItem() to create a new RITM under the same REQ.

    • Copy variables from the original RITM. (To copy Variables if you are using this functionality frequently, it's better to create a custom action to copy the variable values from 1 ritm to another)

    • Assign the RITM to the mapped group.

 Result: one REQ, multiple RITMs (one per checkbox), all with the same variable values but routed to different groups. This keeps the user flow simple (one form, one submission) while giving you clean backend routing.

Regards,
Manikandan Thangaraj

ChiranjeeviR
Kilo Sage

Hi @phugill,

 

please follow below steps as per Requirement

Step 1: Background Script (Standalone Test)

Paste this into Scripts → Background in your dev instance:

(function() {
    // Sys_id of your catalog item
    var catalogItem = 'YOUR_CATALOG_ITEM_SYS_ID';  
    
    // Simulated form input variables (checkboxes + shared data)
    var requested_for = '6816f79cc0a8016401c5a33be04be441'; // sys_id of "Abel Tuter"
    var other_variable = 'Sample Value'; // some other shared variable
    
    // Checkbox selections (true/false)
    var it_systems = true;
    var infosec = true;
    var finance = false;
    
    // Map selections to groups
    var options = [];
    if (it_systems) options.push({group: '287ebd7da9fe198100f92cc8d1d2154e', value: 'IT Systems'});
    if (infosec) options.push({group: '62826bf03710200044e0bfc8bcbe5df1', value: 'Information Security'});
    if (finance) options.push({group: '8a4dde73c6112278017a6a4baf547aa7', value: 'Finance'});
    
    // Create cart
    var cartId = GlideGuid.generate(null);
    var cart = new Cart(cartId);
    
    for (var i=0; i<options.length; i++) {
        var item = cart.addItem(catalogItem, 1);
        
        // Set catalog variables
        cart.setVariable(item, 'requested_for', requested_for);
        cart.setVariable(item, 'other_variable', other_variable);
        cart.setVariable(item, 'selected_area', options[i].value);
        
        // Optional: force assignment group
        var ritm = cart.getCartItems()[i];
        ritm.assignment_group = options[i].group; // sys_id of group
    }
    
    // Place order → creates REQ + RITMs
    var rc = cart.placeOrder();
    gs.info('✅ Request created: ' + rc.number);
})();

above script what it does means

 

  • Simulates checkboxes (it_systems, infosec, finance).

  • For each checked box:

    • Adds the catalog item to the cart.

    • Sets shared variables + selected_area.

    • Assigns the RITM to a group.

  • Creates one REQ with multiple RITMs.

Step 2: Move into Flow Designer

Once you confirm the Background Script works:

 

  • Go to Flow Designer → New Subflow.

  • Inputs:

    • requested_for (Reference → User)

    • other_variable (String)

    • it_systems (Boolean)

    • infosec (Boolean)

    • finance (Boolean)

  • Add a Run Script action and paste the core logic:

(function execute(inputs, outputs) {
    var catalogItem = 'YOUR_CATALOG_ITEM_SYS_ID';
    
    var options = [];
    if (inputs.it_systems) options.push({group: 'IT_GROUP_SYSID', value: 'IT Systems'});
    if (inputs.infosec) options.push({group: 'INFOSEC_GROUP_SYSID', value: 'Information Security'});
    if (inputs.finance) options.push({group: 'FINANCE_GROUP_SYSID', value: 'Finance'});
    
    var cartId = GlideGuid.generate(null);
    var cart = new Cart(cartId);
    
    for (var i=0; i<options.length; i++) {
        var item = cart.addItem(catalogItem, 1);
        cart.setVariable(item, 'requested_for', inputs.requested_for);
        cart.setVariable(item, 'other_variable', inputs.other_variable);
        cart.setVariable(item, 'selected_area', options[i].value);
        
        var ritm = cart.getCartItems()[i];
        ritm.assignment_group = options[i].group;
    }
    
    var rc = cart.placeOrder();
    outputs.requestNumber = rc.number;
})(inputs, outputs);

 

 

 Outputs:

  • requestNumber (String).

Now you can call this subflow in your main Catalog Item Flow.

 

Result:

  • User submits one form with checkboxes.

  • Flow → creates 1 REQ with multiple RITMs.

  • Each RITM is routed to the correct group.

Please mark as Correct Answer/Helpful, if applicable.

ServiceNow Developer

Thanks & Regards,
Chiranjeevi
ServiceNow Developer | | ITSM | | ServiceNow Discovery | | Event Management | | Service Mapping | | CMDB

Please mark as Correct Answer/Helpful, if applicable.