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 RITMs from MRVS

tcorniels
Tera Contributor

Have a catalog item that has a MRVS that I need to parse out into individual RITMs via a workflow script.  I can get it to create the other RITMs but they are blank and will not transfer any of the variable data over from the RITM.  I know I'm close, but just not sure what the hang up is.

 

//Get MRVS and prepare to parse

var mrvs = current.variables.software_request;
var parseMrvs = JSON.parse(mrvs);

// Loop through the MRVS
for (var i = 0; i < parseMrvs.length; i++) {

	//Create RITMS

	var grReqItem = new GlideRecord('sc_req_item');
    grReqItem.initialize();
	grReqItem.cat_item = 'a7d66ee41b90ca10ce6f9683b24bcb4b'; // sys_id for Software Purchasing catalog item
    grReqItem.request = current.request;

    //Get the Next item from the MRVS
    var multiVarset = parseMrvs.getRow(i);


	//set variables
    grReqItem.variables.new_or_existing = multiVarset.new_or_existing;
    grReqItem.variables.epmo_reviewed = multiVarset.epmo_reviewed;
    grReqItem.variables.operating_system = multiVarset.operating_system;
    grReqItem.variables.choose_software = multiVarset.choose_software;
    grReqItem.variables.found_software = multiVarset.found_software;
    grReqItem.variables.product_name = multiVarset.product_name;
    grReqItem.variables.publisher = multiVarset.publisher;
    grReqItem.variables.version = multiVarset.version;
    grReqItem.variables.edition = multiVarset.edition;
    grReqItem.variables.product_sku = multiVarset.product_sku;
    grReqItem.variables.license_type = multiVarset.license_type;
    grReqItem.variables.license_metric = multiVarset.license_metric;
    grReqItem.variables.free_stuff = multiVarset.free_stuff;
    grReqItem.variables.contact_required = multiVarset.contact_required;
    grReqItem.variables.current_rfp = multiVarset.current_rfp;
    grReqItem.variables.number_of_licenses = multiVarset.number_of_licenses;
    grReqItem.variables.unit_cost = multiVarset.unit_cost;
    grReqItem.variables.tax_rate = multiVarset.tax_rate;
    grReqItem.variables.total = multiVarset.total;

    grReqItem.short_description = "Software Purchase for " + product_name;            

//	grReqItem.update();
	grReqItem.insert();

}		
 
6 REPLIES 6

@tcorniels 

Hope you are doing good.

Did my reply answer your question?

💡 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

MaxMixali
Giga Guru

ServiceNow – Split MRVS rows into separate, fully populated RITMs (no blank variables)

Problem
You’re looping a Multi-Row Variable Set (MRVS) and creating additional RITMs via GlideRecord insert, but the new RITMs are blank (variables don’t copy). Also, code like parseMrvs.getRow(i) won’t work server-side.

Why this happens
1) MRVS value on the server is a JSON string; parse with JSON.parse(). The rows are usually under data.rows or just an array depending on how it was saved.
2) Setting variables via gr.variables before insert does NOT create variable rows. Catalog variables live in sc_item_option_mtom (linked to item_option_new questions). You must create those variable rows explicitly or use the Cart API to create the item with variables.

Two supported approaches
A) Cart API (creates RITMs with variables in one go). Best for new REQ.
B) Manual RITM + variable row creation (works when you must attach to the existing REQ).

Since you want items under the same Request (current.request), use approach B below.

Working pattern (server-side, e.g., workflow script step)
---------------------------------------------------------
Assumptions:
- The target catalog item (Software Purchasing) = 'a7d66ee41b90ca10ce6f9683b24bcb4b'
- MRVS variable name on the source item = software_request
- The target item’s variable names match the MRVS row object keys

// 1) Parse MRVS safely
var raw = current.variables.software_request + '';
if (!raw) {
gs.warn('No MRVS data present');
answer = 0;
(function(){})();
}
var parsed = JSON.parse(raw);
var rows = parsed.rows || parsed; // support both shapes: {rows:[...]} or [...]

if (!rows || !rows.length) {
gs.warn('MRVS has no rows');
answer = 0;
(function(){})();
}

// 2) Helper: lookup item_option_new by name for a given cat item
function getQuestionId(catItemSysId, varName) {
var q = new GlideRecord('item_option_new');
q.addQuery('cat_item', catItemSysId);
q.addQuery('name', varName); // variable "Name" (not label)
q.setLimit(1);
q.query();
return q.next() ? q.getUniqueValue() : '';
}

// 3) Insert a variable value row (sc_item_option_mtom)
function setRitmVar(ritmSysId, questionSysId, value) {
if (!ritmSysId || !questionSysId) return;
var mtom = new GlideRecord('sc_item_option_mtom');
mtom.initialize();
mtom.request_item = ritmSysId;
mtom.sc_item_option = questionSysId; // question (item_option_new)
mtom.value = (value === null || value === undefined) ? '' : value.toString();
mtom.insert();
}

// 4) Cache question sys_ids for performance
var CAT_ITEM = 'a7d66ee41b90ca10ce6f9683b24bcb4b';
var qCache = {};
function qid(name){ if(!qCache[name]) qCache[name] = getQuestionId(CAT_ITEM, name); return qCache[name]; }

// 5) For each MRVS row, create a new RITM and variable rows
var created = 0;
for (var i = 0; i < rows.length; i++) {
var r = rows[i];

// Create the RITM
var ritm = new GlideRecord('sc_req_item');
ritm.initialize();
ritm.cat_item = CAT_ITEM;
ritm.request = current.request; // keeps same REQ
ritm.short_description = 'Software Purchase for ' + (r.product_name || '(unspecified)');
var ritmSysId = ritm.insert();

// Now set variable values by creating sc_item_option_mtom rows
// Map only the variables that exist on the target item
setRitmVar(ritmSysId, qid('new_or_existing'), r.new_or_existing);
setRitmVar(ritmSysId, qid('epmo_reviewed'), r.epmo_reviewed);
setRitmVar(ritmSysId, qid('operating_system'), r.operating_system);
setRitmVar(ritmSysId, qid('choose_software'), r.choose_software);
setRitmVar(ritmSysId, qid('found_software'), r.found_software);
setRitmVar(ritmSysId, qid('product_name'), r.product_name);
setRitmVar(ritmSysId, qid('publisher'), r.publisher);
setRitmVar(ritmSysId, qid('version'), r.version);
setRitmVar(ritmSysId, qid('edition'), r.edition);
setRitmVar(ritmSysId, qid('product_sku'), r.product_sku);
setRitmVar(ritmSysId, qid('license_type'), r.license_type);
setRitmVar(ritmSysId, qid('license_metric'), r.license_metric);
setRitmVar(ritmSysId, qid('free_stuff'), r.free_stuff);
setRitmVar(ritmSysId, qid('contact_required'), r.contact_required);
setRitmVar(ritmSysId, qid('current_rfp'), r.current_rfp);
setRitmVar(ritmSysId, qid('number_of_licenses'), r.number_of_licenses);
setRitmVar(ritmSysId, qid('unit_cost'), r.unit_cost);
setRitmVar(ritmSysId, qid('tax_rate'), r.tax_rate);
setRitmVar(ritmSysId, qid('total'), r.total);

created++;
}

gs.info('Created ' + created + ' child RITMs with populated variables.');

Notes & gotchas
---------------
- parseMrvs.getRow(i) is not valid in server-side JSON; use rows[i].
- Variable names must match the “Name” (not the Label) on the target item’s variables.
- If a variable doesn’t exist on the target item, qid(name) returns empty and the value is skipped.
- If you can accept a new Request instead of using the existing one, consider the Cart API:
var cart = new sn_sc.Cart();
var vars = { product_name: 'Example', unit_cost: '10' };
cart.addItem(CAT_ITEM, 1, vars);
var req = cart.placeOrder(); // creates REQ + RITM with variables
But cart.placeOrder() always creates a new REQ; not ideal when you must use current.request.

- For checkboxes / choice lists, pass the internal value (not the label).
- For reference variables, pass the sys_id of the referenced record.
- For date/time variables, pass a valid GlideDateTime string.

TL;DR
- Parse MRVS as JSON and iterate rows correctly.
- When creating RITMs via GlideRecord, also create variable rows in sc_item_option_mtom for each question on the target item.
- Your previous approach left RITM variables blank because gr.variables does not auto-create variable records.