georgeprad
Giga Expert

I have wrttent the following code that can be used as a background script to help achieve this. I am only pulling active RITMs with atleast one open task. You may change the filters as per your need. You may also need to check the tables the variables reference as this could bvary between instances. I am attaching this to the user record from where it can be downloaded. I have also put a limit on each file as I ran into issues downloading this data without putting a limit.

 

 

(function() {
var MAX_ATTACHMENT_BYTES = 14 * 1024 * 1024; // 14 MB
var userSysId = gs.getUserID();
var userTable = 'sys_user'; // Attach to current user

// Helper: Check if a value looks like a sys_id
function isSysID(val) {
return typeof val === 'string' && /^[0-9a-fA-F]{32}$/.test(val);
}

// Sys ID cache for performance
var sysIdCache = {};

function resolveSysID(sysID) {
if (!sysID || !isSysID(sysID)) return sysID;
if (sysIdCache[sysID]) return sysIdCache[sysID];

var tablesToCheck = [
'sys_user', 'cmn_location', 'sc_cat_item', 'sc_req_item',
'incident', 'change_request', 'cmdb_ci_service',
'sys_user_group', 'cmdb_ci_computer', 'cmn_cost_center',
'cmn_department', 'core_company', 'u_services'
];

for (var i = 0; i < tablesToCheck.length; i++) {
var gr = new GlideRecord(tablesToCheck[i]);
if (gr.isValid() && gr.get(sysID)) {
var display = gr.getDisplayValue();
sysIdCache[sysID] = display;
return display;
}
}

sysIdCache[sysID] = sysID; // fallback
return sysID;
}

// Get all comments for a RITM
function getComments(ritmSysID) {
var entries = [];
var grJournal = new GlideRecord('sys_journal_field');
grJournal.addQuery('element_id', ritmSysID);
grJournal.addQuery('element', 'IN', 'comments,work_notes');
grJournal.orderBy('sys_created_on');
grJournal.query();

while (grJournal.next()) {
var val = grJournal.value.toString().replace(/(\r\n|\n|\r)/g, ' ');
entries.push(val);
}

if (entries.length === 0) return '';
var combined = entries.join(' | ');
combined = '"' + combined.replace(/"/g, '""') + '"';
return combined;
}

// Get all worknotes from SCTASKs for a RITM

function getTaskWorknotes(ritmSysID) {
var entries = [];
var taskGR = new GlideRecord('sc_task');
taskGR.addQuery('request_item', ritmSysID);
taskGR.query();

while (taskGR.next()) {
var journalGR = new GlideRecord('sys_journal_field');
journalGR.addQuery('element_id', taskGR.sys_id);
journalGR.addQuery('element', 'work_notes');
journalGR.orderBy('sys_created_on');
journalGR.query();
while (journalGR.next()) {
var val = journalGR.value.toString().replace(/(\r\n|\n|\r)/g, ' ');
entries.push(val);
}
}

if (entries.length === 0) return '';
var combined = entries.join(' | ');
combined = '"' + combined.replace(/"/g, '""') + '"';
return combined;
}

// Get SCTASK numbers and sys_ids for a RITM

function getTaskNumbersAndSysIds(ritmSysID) {
var pairs = [];
var taskGR = new GlideRecord('sc_task');
taskGR.addQuery('request_item', ritmSysID);
taskGR.query();

while (taskGR.next()) {
pairs.push(taskGR.number.toString() + ' - ' + taskGR.sys_id.toString());
}

if (pairs.length === 0) return '';
var combined = pairs.join(' | ');
combined = '"' + combined.replace(/"/g, '""') + '"';
return combined;
}

var ritmGR = new GlideRecord('sc_req_item');
ritmGR.addQuery('active', true);
ritmGR.orderByDesc('sys_created_on');
ritmGR.query();

var csvHeader = 'RITM Number,RITM Sys ID,REQ Number,SCTASKs (Number - Sys ID),RITM Item Name,Requested For,Opened By,Opened At,Assignment Group,Assigned To,Comments,Worknotes from Tasks,Variable Name,Variable Value\n';
var csvLines = [csvHeader];
var attachmentIndex = 1;

while (ritmGR.next()) {
// Only include RITMs with active SCTASKs
var sctaskGR = new GlideRecord('sc_task');
sctaskGR.addQuery('request_item', ritmGR.sys_id);
sctaskGR.addQuery('active', true);
sctaskGR.query();
if (!sctaskGR.hasNext()) continue;

var ritmNumber = ritmGR.number.toString();
var reqNumber = ritmGR.request.number.toString();
var taskNumbersSysIds = getTaskNumbersAndSysIds(ritmGR.sys_id);
var itemName = ritmGR.cat_item ? ritmGR.cat_item.getDisplayValue() : '';
var requestedFor = ritmGR.request.requested_for.getDisplayValue();
var openedBy = ritmGR.opened_by ? ritmGR.opened_by.getDisplayValue() : '';
var openedAt = ritmGR.opened_at ? ritmGR.opened_at.getDisplayValue() : '';
var assignmentGroup = ritmGR.assignment_group ? ritmGR.assignment_group.getDisplayValue() : '';
var assignedTo = ritmGR.assigned_to ? ritmGR.assigned_to.getDisplayValue() : '';
var comments = getComments(ritmGR.sys_id);
var taskWorknotes = getTaskWorknotes(ritmGR.sys_id);

// Variables
var m2m = new GlideRecord('sc_item_option_mtom');
m2m.addQuery('request_item', ritmGR.sys_id);
m2m.query();

if (!m2m.hasNext()) {
csvLines.push([ritmNumber, ritmGR.sys_id, reqNumber, taskNumbersSysIds, itemName, requestedFor, openedBy, openedAt, assignmentGroup, assignedTo, comments, taskWorknotes, '', ''].join(','));
} else {
while (m2m.next()) {
var opt = m2m.sc_item_option.getRefRecord();
var varName = opt.item_option_new.getDisplayValue();
var varValue = opt.value ? opt.value.toString().replace(/(\r\n|\n|\r|,)/g, ' ') : '';
varValue = resolveSysID(varValue);

csvLines.push([ritmNumber, ritmGR.sys_id, reqNumber, taskNumbersSysIds, itemName, requestedFor, openedBy, openedAt, assignmentGroup, assignedTo, comments, taskWorknotes, varName, varValue].join(','));
}
}

// Check attachment size
var csvContent = csvLines.join('\n');
if (csvContent.length >= MAX_ATTACHMENT_BYTES) {
var grUser = new GlideRecord(userTable);
if (grUser.get(userSysId)) {
var attachment = new GlideSysAttachment();
attachment.write(grUser, 'RITM_Export_Part_' + attachmentIndex + '.csv', 'text/csv', csvContent);
gs.info(' Created attachment RITM_Export_Part_' + attachmentIndex + '.csv with ' + csvLines.length + ' lines');
}
attachmentIndex++;
csvLines = [csvHeader]; // reset for next batch
}
}

// Write final attachment if remaining lines
if (csvLines.length > 1) {
var grUser = new GlideRecord(userTable);
if (grUser.get(userSysId)) {
var attachment = new GlideSysAttachment();
attachment.write(grUser, 'RITM_Export_Part_' + attachmentIndex + '.csv', 'text/csv', csvLines.join('\n'));
gs.info(' Created final attachment RITM_Export_Part_' + attachmentIndex + '.csv');
}
}

gs.info(' Export complete. Total RITMs processed: ' + ritmGR.getRowCount());
})();

View solution in original post