request-management

安装量: 53
排名: #13968

安装

npx skills add https://github.com/groeimetai/snow-flow --skill request-management

Request Management handles service requests from catalog items through fulfillment.

Request Hierarchy

Request (sc_request)
    ├── Request Item (sc_req_item) - RITM
    │   ├── Catalog Tasks (sc_task)
    │   └── Variables (sc_item_option_mtom)
    └── Request Item
        └── Catalog Tasks

Key Tables

| sc_request | Parent request record

| sc_req_item | Requested items (RITM)

| sc_task | Fulfillment tasks

| sc_item_option_mtom | Variable values

| sc_cat_item | Catalog item definitions

Request Items (ES5)

Create Request Programmatically

// Create request and RITM (ES5 ONLY!)
function createServiceRequest(catalogItemName, requestedFor, variables) {
    // Get catalog item
    var catItem = new GlideRecord('sc_cat_item');
    if (!catItem.get('name', catalogItemName)) {
        gs.error('Catalog item not found: ' + catalogItemName);
        return null;
    }

    // Create request
    var request = new GlideRecord('sc_request');
    request.initialize();
    request.setValue('requested_for', requestedFor);
    request.setValue('opened_by', gs.getUserID());
    request.setValue('description', 'Request for ' + catalogItemName);
    var requestSysId = request.insert();

    // Create RITM
    var ritm = new GlideRecord('sc_req_item');
    ritm.initialize();
    ritm.setValue('request', requestSysId);
    ritm.setValue('cat_item', catItem.getUniqueValue());
    ritm.setValue('requested_for', requestedFor);
    ritm.setValue('quantity', 1);

    var ritmSysId = ritm.insert();

    // Set variables
    if (variables) {
        setRITMVariables(ritmSysId, variables);
    }

    return {
        request: request.getValue('number'),
        ritm: ritm.getValue('number'),
        request_sys_id: requestSysId,
        ritm_sys_id: ritmSysId
    };
}

function setRITMVariables(ritmSysId, variables) {
    var ritm = new GlideRecord('sc_req_item');
    if (!ritm.get(ritmSysId)) return;

    for (var varName in variables) {
        if (variables.hasOwnProperty(varName)) {
            ritm.variables[varName] = variables[varName];
        }
    }
    ritm.update();
}

Query Request Items

// Get user's open requests (ES5 ONLY!)
function getUserRequests(userSysId, includeCompleted) {
    var requests = [];

    var ritm = new GlideRecord('sc_req_item');
    ritm.addQuery('requested_for', userSysId);

    if (!includeCompleted) {
        ritm.addQuery('state', '!=', '3');  // Not Closed Complete
        ritm.addQuery('state', '!=', '4');  // Not Closed Incomplete
    }

    ritm.orderByDesc('sys_created_on');
    ritm.query();

    while (ritm.next()) {
        requests.push({
            sys_id: ritm.getUniqueValue(),
            number: ritm.getValue('number'),
            short_description: ritm.getValue('short_description'),
            cat_item: ritm.cat_item.getDisplayValue(),
            state: ritm.state.getDisplayValue(),
            stage: ritm.stage.getDisplayValue(),
            opened_at: ritm.getValue('sys_created_on'),
            due_date: ritm.getValue('due_date')
        });
    }

    return requests;
}

Fulfillment Tasks (ES5)

Create Catalog Tasks

// Create fulfillment tasks for RITM (ES5 ONLY!)
function createFulfillmentTasks(ritmSysId, taskDefinitions) {
    var ritm = new GlideRecord('sc_req_item');
    if (!ritm.get(ritmSysId)) {
        return [];
    }

    var createdTasks = [];

    for (var i = 0; i < taskDefinitions.length; i++) {
        var taskDef = taskDefinitions[i];

        var task = new GlideRecord('sc_task');
        task.initialize();
        task.setValue('request_item', ritmSysId);
        task.setValue('request', ritm.getValue('request'));
        task.setValue('short_description', taskDef.description);
        task.setValue('assignment_group', taskDef.assignmentGroup);
        task.setValue('order', (i + 1) * 100);

        // Calculate due date if specified
        if (taskDef.daysToComplete) {
            var dueDate = new GlideDateTime();
            dueDate.addDaysLocalTime(taskDef.daysToComplete);
            task.setValue('due_date', dueDate);
        }

        var taskSysId = task.insert();
        createdTasks.push({
            sys_id: taskSysId,
            number: task.getValue('number')
        });
    }

    return createdTasks;
}

// Example usage
var tasks = createFulfillmentTasks(ritmSysId, [
    { description: 'Verify request details', assignmentGroup: 'Service Desk', daysToComplete: 1 },
    { description: 'Provision access', assignmentGroup: 'IAM Team', daysToComplete: 2 },
    { description: 'Notify user', assignmentGroup: 'Service Desk', daysToComplete: 1 }
]);

Auto-close RITM on Task Completion

// Business Rule: after, update, sc_task (ES5 ONLY!)
(function executeRule(current, previous) {
    // Check if task was just closed
    if (current.state.changesTo('3') || current.state.changesTo('4')) {
        checkAndCloseRITM(current.getValue('request_item'));
    }
})(current, previous);

function checkAndCloseRITM(ritmSysId) {
    // Check if all tasks are complete
    var openTasks = new GlideAggregate('sc_task');
    openTasks.addQuery('request_item', ritmSysId);
    openTasks.addQuery('state', 'NOT IN', '3,4,7');  // Not closed or cancelled
    openTasks.addAggregate('COUNT');
    openTasks.query();

    if (openTasks.next()) {
        var count = parseInt(openTasks.getAggregate('COUNT'), 10);
        if (count === 0) {
            // All tasks complete, close RITM
            var ritm = new GlideRecord('sc_req_item');
            if (ritm.get(ritmSysId)) {
                ritm.state = 3;  // Closed Complete
                ritm.update();
            }
        }
    }
}

Variable Management (ES5)

Access RITM Variables

// Get variable values from RITM (ES5 ONLY!)
function getRITMVariables(ritmSysId) {
    var variables = {};

    var ritm = new GlideRecord('sc_req_item');
    if (!ritm.get(ritmSysId)) {
        return variables;
    }

    // Get all variable values
    var varValue = new GlideRecord('sc_item_option_mtom');
    varValue.addQuery('request_item', ritmSysId);
    varValue.query();

    while (varValue.next()) {
        var varName = varValue.sc_item_option.item_option_new.name.toString();
        var value = varValue.getValue('sc_item_option');

        // Get display value for reference fields
        var varDef = varValue.sc_item_option.item_option_new.getRefRecord();
        if (varDef.getValue('type') === '8') {  // Reference
            var refRecord = new GlideRecord(varDef.getValue('reference'));
            if (refRecord.get(value)) {
                variables[varName] = {
                    value: value,
                    display_value: refRecord.getDisplayValue()
                };
            }
        } else {
            variables[varName] = {
                value: value,
                display_value: varValue.sc_item_option.getDisplayValue()
            };
        }
    }

    return variables;
}

Validate Variables

// Validate RITM variables (ES5 ONLY!)
function validateRITMVariables(ritmSysId) {
    var errors = [];

    var ritm = new GlideRecord('sc_req_item');
    if (!ritm.get(ritmSysId)) {
        return ['RITM not found'];
    }

    // Get catalog item variable definitions
    var catItem = ritm.cat_item.getRefRecord();

    var varDef = new GlideRecord('item_option_new');
    varDef.addQuery('cat_item', catItem.getUniqueValue());
    varDef.addQuery('mandatory', true);
    varDef.query();

    while (varDef.next()) {
        var varName = varDef.getValue('name');
        var varValue = ritm.variables[varName];

        if (!varValue || varValue.toString() === '') {
            errors.push('Missing required variable: ' + varDef.getValue('question_text'));
        }
    }

    return errors;
}

Request Approvals (ES5)

Check Approval Status

// Get approval status for request (ES5 ONLY!)
function getRequestApprovalStatus(requestSysId) {
    var approvals = [];

    var approval = new GlideRecord('sysapproval_approver');
    approval.addQuery('sysapproval', requestSysId);
    approval.query();

    while (approval.next()) {
        approvals.push({
            approver: approval.approver.getDisplayValue(),
            state: approval.state.getDisplayValue(),
            comments: approval.getValue('comments'),
            sys_updated_on: approval.getValue('sys_updated_on')
        });
    }

    // Determine overall status
    var pending = 0;
    var approved = 0;
    var rejected = 0;

    for (var i = 0; i < approvals.length; i++) {
        var state = approvals[i].state;
        if (state === 'Requested') pending++;
        else if (state === 'Approved') approved++;
        else if (state === 'Rejected') rejected++;
    }

    return {
        approvals: approvals,
        summary: {
            pending: pending,
            approved: approved,
            rejected: rejected,
            overall: rejected > 0 ? 'Rejected' : (pending > 0 ? 'Pending' : 'Approved')
        }
    };
}

MCP Tool Integration

Available Tools

| snow_query_table | Query requests and RITMs

| snow_find_artifact | Find catalog items

| snow_execute_script_with_output | Test request scripts

| snow_create_catalog_item | Create catalog items

Example Workflow

// 1. Query open requests
await snow_query_table({
    table: 'sc_req_item',
    query: 'state!=3^state!=4^requested_for=javascript:gs.getUserID()',
    fields: 'number,short_description,cat_item,state,stage'
});

// 2. Get request details
await snow_execute_script_with_output({
    script: `
        var vars = getRITMVariables('ritm_sys_id');
        gs.info(JSON.stringify(vars));
    `
});

// 3. Check approvals
await snow_query_table({
    table: 'sysapproval_approver',
    query: 'sysapproval=request_sys_id',
    fields: 'approver,state,comments'
});

Best Practices

  • Clear Descriptions - User-friendly short descriptions

  • Variable Validation - Validate before processing

  • Task Ordering - Logical fulfillment sequence

  • SLA Tracking - Set appropriate due dates

  • Notifications - Keep requesters informed

  • Approval Rules - Configure appropriate approvals

  • Auto-closure - Close RITMs when tasks complete

  • ES5 Only - No modern JavaScript syntax

返回排行榜