Interested in a ServiceNow event built for developers? Registration for now[dev]26 is officially open!

Create Multiple RITMs from MRVS Rows Under the Same REQ and Populate Variables

AidaS
Tera Expert

Hi everyone,

I have a Catalog Item with an MRVS for bulk Server Access. When Bulk Access = Yes, each MRVS row should create one RITM, and all RITMs should belong to the same existing REQ.

I can use Create Record → sc_req_item and link each new RITM to the existing REQ, but I cannot populate the catalog variables on the newly created RITM from the current MRVS row.

I also tried Submit Catalog Item Request, which allows variable mapping, but it creates a new REQ instead of using the existing one.

What is the recommended OOB/Flow Designer approach for this? Would a Custom Action + CartJS be appropriate, or is there a better pattern?

2 ACCEPTED SOLUTIONS

Hi @Aditya_hublikar  thank you for following up. I’m still working on it, but I’m currently stuck with the REQ handling.

The MRVS is working and the Flow correctly loops through all the rows. The custom action also runs for each row and creates the RITMs, but when I use CartJS, it creates empty REQs for the generated RITMs.

 

AidaS_0-1789385289639.pngAidaS_1-1789385308332.png

AidaS_2-1789385325832.png 

AidaS_3-1789385385358.png

 

function getSysId(value) {
    if (!value) return '';
    if (typeof value == 'string') return value;
    if (value.getUniqueValue) return value.getUniqueValue();
    return '';
}

(function execute(inputs, outputs) {

    var existingReqSysId = getSysId(inputs.original_request);
    var ritm = inputs.requested_item;
    var catalogItem = ritm.cat_item.getRefRecord(); 
    var catalogItemSysId = catalogItem.getUniqueValue(); 
    try {

    var mrvsRows = [{
    'mrvs_server_name': getSysId(inputs.server_name),
    'mrvs_technical_owner': getSysId(inputs.technical_owner),
    'mrvs_virtual_machine_name': getSysId(inputs.virtual_machine_name),
    'mrvs_what_access': inputs.what_access + ''
}];

        var mrvsJSON = JSON.stringify(mrvsRows);

        //  Create CartJS
        var cart = new sn_sc.CartJS();

        // Build catalog item payload
        var itemPayload = {
            'sysparm_id': catalogItemSysId,
            'sysparm_quantity': '1',
            'variables': {
                'multi_row_variable_set': mrvsJSON,
                 'select_the_permission_level_server': inputs.permission_level + '',
                 'full_sql': inputs.full_sql,
                 'requested_for': getSysId(inputs.requested_for),
            }
        };

        gs.info('[Server Access] CartJS PAYLOAD = ' + JSON.stringify(itemPayload));

        // Submit the catalog item
        var cartResult = cart.orderNow(itemPayload);

    
        //  Get temporary REQ
        var newRequestSysId = cartResult.request_id + '';

        gs.info('[Server Access] Temporary REQ sys_id: ' + newRequestSysId);

        var ritmGR = new GlideRecord('sc_req_item');
        ritmGR.addQuery('request', newRequestSysId);
        ritmGR.addQuery('cat_item', catalogItemSysId);
        ritmGR.query();

        if (ritmGR.next()) {
            gs.info('New RITM found: ' + ritmGR.getValue('number'));
            ritmGR.setValue('request', existingReqSysId);
            var updateResult = ritmGR.update();

            gs.info('[Server Access] RITM moved to original REQ');
            gs.info('[Server Access] Updated RITM sys_id: ' + updateResult);
            gs.info('[Server Access] Original REQ: ' + existingReqSysId);

            outputs.ritm_number = ritmGR.getValue('number');

        } else {
            gs.error(' ERROR: Could not find newly created RITM.');
        }

    } catch (ex) {
        gs.error('[Server Access] ERROR: ' + ex.getMessage());
        gs.error('[Server Access] ERROR details: ' + ex);
    }

})(inputs, outputs);

 

View solution in original post

Hello @AidaS ,

 

Yes you just need to delete those requests :

Aditya_hublikar_0-1789397602569.png

 

View solution in original post

5 REPLIES 5

Ankur Bawiskar
Tera Patron

@AidaS 

you can iterate each MRVS row and use OOTB flow action "Submit Catalog Item Request" and it will create REQ and RITM

Yes it will create new REQ and new RITM, you can cancel the new REQ and update the new RITM with the existing REQ by using "Update Record" flow action

I shared solution last year, check and enhance

Create multiple RITM based on data in MRVS using Flow Designer 

 

AnkurBawiskar_1-1788956108071.gif

 

💡 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  ||  ✨ 10x ServiceNow MVP  ||  ✨ ServiceNow Community Leader

Aditya_hublikar
Giga Sage

Hello @AidaS ,

 

I have tried your use case :

 Created custom action in flow designer to create individual ritm and its code is as below :

(function execute(inputs, outputs) {


    var existingReqSysId = inputs.req;
    var catalogItemSysId = inputs.catid;

   try {
    var mrvs = {
        server: inputs.server,
        access: inputs.access
    };

    var existingReqSysId = existingReqSysId;
    var catalogItemSysId = catalogItemSysId;


    var mrvsRows = [
        {
            server: mrvs.server + '',
            access: mrvs.access + ''
        }
    ];

    var mrvsJSON = JSON.stringify(mrvsRows);
    gs.info('MRVS JSON = ' + mrvsJSON);

    var cart = new sn_sc.CartJS();

    var itemPayload = {
        'sysparm_id': catalogItemSysId,
        'sysparm_quantity': '1',
        'variables': {
            'mrvs_usecase': mrvsJSON // Set MRVS variable container name
        }
    };

    var cartResult = cart.orderNow(itemPayload);
    
    var newRequestSysId = cartResult.request_id; 
    gs.info('Temporary REQ = ' + newRequestSysId);

    var ritmGR = new GlideRecord('sc_req_item');
    ritmGR.addQuery('request', newRequestSysId);
    ritmGR.query();

    while (ritmGR.next()) {

        gs.info(
            'RITM = ' +
            ritmGR.getValue('number')
        );

        gs.info(
            'RITM sys_id = ' +
            ritmGR.getUniqueValue()
        );

        var optionGR = new GlideRecord('sc_item_option_mtom');
        optionGR.addQuery('request_item', ritmGR.getUniqueValue());
        optionGR.query();

        while (optionGR.next()) {
            var itemOption = optionGR.sc_item_option.getRefRecord();
            gs.info(
                'VARIABLE = ' +
                itemOption.getDisplayValue('item_option_new') +
                ' VALUE = ' +
                itemOption.getValue('value')
            );
        }

        ritmGR.setValue('request', existingReqSysId);
        ritmGR.update();
    }


    var emptyReq = new GlideRecord('sc_request');
    if (emptyReq.get(newRequestSysId)) {
        emptyReq.deleteRecord();
        gs.info(
            'Temporary REQ deleted = ' +
            newRequestSysId
        );
    }
    outputs.ritmnum= ritmGR.number.toString();

} catch (ex) {
    var message = ex.getMessage();
    gs.error("CartJS Execution Error: " + message);
}


})(inputs, outputs);

 

Aditya_hublikar_0-1789019463178.png

 

Aditya_hublikar_1-1789019501832.png

Aditya_hublikar_2-1789019537101.png

Aditya_hublikar_3-1789019564095.png

 

 

Called it in flow :

Aditya_hublikar_4-1789019758228.png

Aditya_hublikar_5-1789019809160.png

 

 

Outcome :

Aditya_hublikar_6-1789019842398.png

Aditya_hublikar_7-1789019882942.png

Aditya_hublikar_8-1789019904849.png

 

 

If this helps you then mark it as helpful and accept as solution.

Regards,

Aditya

Hello @AidaS ,

 

I hope you are doing well . Does your query is resolved ? If yes then accept as solution and  close this thread .

Hi @Aditya_hublikar  thank you for following up. I’m still working on it, but I’m currently stuck with the REQ handling.

The MRVS is working and the Flow correctly loops through all the rows. The custom action also runs for each row and creates the RITMs, but when I use CartJS, it creates empty REQs for the generated RITMs.

 

AidaS_0-1789385289639.pngAidaS_1-1789385308332.png

AidaS_2-1789385325832.png 

AidaS_3-1789385385358.png

 

function getSysId(value) {
    if (!value) return '';
    if (typeof value == 'string') return value;
    if (value.getUniqueValue) return value.getUniqueValue();
    return '';
}

(function execute(inputs, outputs) {

    var existingReqSysId = getSysId(inputs.original_request);
    var ritm = inputs.requested_item;
    var catalogItem = ritm.cat_item.getRefRecord(); 
    var catalogItemSysId = catalogItem.getUniqueValue(); 
    try {

    var mrvsRows = [{
    'mrvs_server_name': getSysId(inputs.server_name),
    'mrvs_technical_owner': getSysId(inputs.technical_owner),
    'mrvs_virtual_machine_name': getSysId(inputs.virtual_machine_name),
    'mrvs_what_access': inputs.what_access + ''
}];

        var mrvsJSON = JSON.stringify(mrvsRows);

        //  Create CartJS
        var cart = new sn_sc.CartJS();

        // Build catalog item payload
        var itemPayload = {
            'sysparm_id': catalogItemSysId,
            'sysparm_quantity': '1',
            'variables': {
                'multi_row_variable_set': mrvsJSON,
                 'select_the_permission_level_server': inputs.permission_level + '',
                 'full_sql': inputs.full_sql,
                 'requested_for': getSysId(inputs.requested_for),
            }
        };

        gs.info('[Server Access] CartJS PAYLOAD = ' + JSON.stringify(itemPayload));

        // Submit the catalog item
        var cartResult = cart.orderNow(itemPayload);

    
        //  Get temporary REQ
        var newRequestSysId = cartResult.request_id + '';

        gs.info('[Server Access] Temporary REQ sys_id: ' + newRequestSysId);

        var ritmGR = new GlideRecord('sc_req_item');
        ritmGR.addQuery('request', newRequestSysId);
        ritmGR.addQuery('cat_item', catalogItemSysId);
        ritmGR.query();

        if (ritmGR.next()) {
            gs.info('New RITM found: ' + ritmGR.getValue('number'));
            ritmGR.setValue('request', existingReqSysId);
            var updateResult = ritmGR.update();

            gs.info('[Server Access] RITM moved to original REQ');
            gs.info('[Server Access] Updated RITM sys_id: ' + updateResult);
            gs.info('[Server Access] Original REQ: ' + existingReqSysId);

            outputs.ritm_number = ritmGR.getValue('number');

        } else {
            gs.error(' ERROR: Could not find newly created RITM.');
        }

    } catch (ex) {
        gs.error('[Server Access] ERROR: ' + ex.getMessage());
        gs.error('[Server Access] ERROR details: ' + ex);
    }

})(inputs, outputs);