catalog-items

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Service Catalog Development for ServiceNow

ServiceNow服务目录开发

The Service Catalog allows users to request services and items through a self-service portal.
服务目录允许用户通过自助门户请求服务和项目。

Catalog Components

目录组件

ComponentPurposeExample
CatalogContainer for categoriesIT Service Catalog
CategoryGroup of itemsHardware, Software
ItemRequestable serviceNew Laptop Request
VariableForm field on itemLaptop Model dropdown
Variable SetReusable variable groupUser Details
ProducerCreates records directlyReport an Incident
Order GuideMulti-item wizardNew Employee Setup
组件用途示例
目录分类的容器IT服务目录
分类项目组硬件、软件
项目可请求的服务新笔记本电脑申请
变量项目上的表单字段笔记本电脑型号下拉框
变量集可复用的变量组用户详情
生成器直接创建记录上报事件
订购指南多项目向导新员工入职设置

Catalog Item Structure

目录项结构

Catalog Item: Request New Laptop
├── Variables
│   ├── laptop_model (Reference: cmdb_model)
│   ├── reason (Multi-line text)
│   └── urgency (Choice: Low, Medium, High)
├── Variable Sets
│   └── Delivery Information (Address, Contact)
├── Catalog Client Scripts
│   ├── onLoad: Set defaults
│   └── onChange: Update price
├── Workflows/Flows
│   └── Laptop Approval Flow
└── Fulfillment
    └── Creates Task for IT
Catalog Item: Request New Laptop
├── Variables
│   ├── laptop_model (Reference: cmdb_model)
│   ├── reason (Multi-line text)
│   └── urgency (Choice: Low, Medium, High)
├── Variable Sets
│   └── Delivery Information (Address, Contact)
├── Catalog Client Scripts
│   ├── onLoad: Set defaults
│   └── onChange: Update price
├── Workflows/Flows
│   └── Laptop Approval Flow
└── Fulfillment
    └── Creates Task for IT

Variable Types

变量类型

TypeUse CaseExample
Single Line TextShort inputEmployee ID
Multi Line TextLong inputBusiness Justification
Select BoxSingle choicePriority
Check BoxYes/NoExpress Delivery
ReferenceLink to tableRequested For
DateDate pickerNeeded By Date
Lookup Select BoxFiltered referenceModel by Category
List CollectorMultiple selectionsCC Recipients
Container Start/EndVisual groupingHardware Options
MacroCustom widgetCost Calculator
类型使用场景示例
单行文本短输入员工ID
多行文本长输入业务说明
选择框单选优先级
复选框是/否加急配送
引用链接到表格申请人
日期日期选择器需要日期
查找选择框过滤后的引用按分类筛选型号
列表收集器多选抄送收件人
容器开始/结束视觉分组硬件选项
自定义小部件成本计算器

Creating Catalog Variables

创建目录变量

Basic Variable

基础变量

javascript
// Via MCP
snow_create_catalog_variable({
  catalog_item: 'laptop_request',
  name: 'laptop_model',
  type: 'reference',
  reference: 'cmdb_model',
  reference_qual: 'category=computer',
  mandatory: true,
  order: 100
});
javascript
// Via MCP
snow_create_catalog_variable({
  catalog_item: 'laptop_request',
  name: 'laptop_model',
  type: 'reference',
  reference: 'cmdb_model',
  reference_qual: 'category=computer',
  mandatory: true,
  order: 100
});

Variable with Dynamic Default

带动态默认值的变量

javascript
// Variable: requested_for
// Type: Reference (sys_user)
// Default value (script):
javascript:gs.getUserID()
javascript
// Variable: requested_for
// Type: Reference (sys_user)
// Default value (script):
javascript:gs.getUserID()

Variable with Reference Qualifier

带引用限定符的变量

javascript
// Variable: assignment_group
// Type: Reference (sys_user_group)
// Reference Qualifier:

// Simple:
active=true^type=it

// Dynamic (Script):
javascript: 'active=true^manager=' + gs.getUserID()

// Advanced (using current variables):
javascript: 'u_department=' + current.variables.department
javascript
// Variable: assignment_group
// Type: Reference (sys_user_group)
// Reference Qualifier:

// Simple:
active=true^type=it

// Dynamic (Script):
javascript: 'active=true^manager=' + gs.getUserID()

// Advanced (using current variables):
javascript: 'u_department=' + current.variables.department

Catalog Client Scripts

目录客户端脚本

Set Defaults onLoad

加载时设置默认值

javascript
function onLoad() {
  // Set default values
  g_form.setValue('urgency', 'low');

  // Hide admin-only fields
  if (!g_user.hasRole('catalog_admin')) {
    g_form.setDisplay('cost_center', false);
  }

  // Set default date to tomorrow
  var tomorrow = new GlideDateTime();
  tomorrow.addDays(1);
  g_form.setValue('needed_by', tomorrow.getDate().getValue());
}
javascript
function onLoad() {
  // Set default values
  g_form.setValue('urgency', 'low');

  // Hide admin-only fields
  if (!g_user.hasRole('catalog_admin')) {
    g_form.setDisplay('cost_center', false);
  }

  // Set default date to tomorrow
  var tomorrow = new GlideDateTime();
  tomorrow.addDays(1);
  g_form.setValue('needed_by', tomorrow.getDate().getValue());
}

Dynamic Pricing onChange

变更时动态计算价格

javascript
function onChange(control, oldValue, newValue, isLoading) {
  if (isLoading) return;

  // Get price from selected model
  var ga = new GlideAjax('CatalogUtils');
  ga.addParam('sysparm_name', 'getModelPrice');
  ga.addParam('sysparm_model', newValue);
  ga.getXMLAnswer(function(price) {
    g_form.setValue('item_price', price);
    updateTotal();
  });
}

function updateTotal() {
  var price = parseFloat(g_form.getValue('item_price')) || 0;
  var quantity = parseInt(g_form.getValue('quantity')) || 1;
  g_form.setValue('total_cost', (price * quantity).toFixed(2));
}
javascript
function onChange(control, oldValue, newValue, isLoading) {
  if (isLoading) return;

  // Get price from selected model
  var ga = new GlideAjax('CatalogUtils');
  ga.addParam('sysparm_name', 'getModelPrice');
  ga.addParam('sysparm_model', newValue);
  ga.getXMLAnswer(function(price) {
    g_form.setValue('item_price', price);
    updateTotal();
  });
}

function updateTotal() {
  var price = parseFloat(g_form.getValue('item_price')) || 0;
  var quantity = parseInt(g_form.getValue('quantity')) || 1;
  g_form.setValue('total_cost', (price * quantity).toFixed(2));
}

Validation onSubmit

提交时验证

javascript
function onSubmit() {
  // Validate business justification for high-cost items
  var cost = parseFloat(g_form.getValue('total_cost'));
  var justification = g_form.getValue('business_justification');

  if (cost > 1000 && !justification) {
    g_form.showFieldMsg('business_justification',
      'Required for items over $1000', 'error');
    return false;
  }

  // Validate date is in future
  var neededBy = g_form.getValue('needed_by');
  var today = new GlideDateTime().getDate().getValue();
  if (neededBy < today) {
    g_form.showFieldMsg('needed_by',
      'Date must be in the future', 'error');
    return false;
  }

  return true;
}
javascript
function onSubmit() {
  // Validate business justification for high-cost items
  var cost = parseFloat(g_form.getValue('total_cost'));
  var justification = g_form.getValue('business_justification');

  if (cost > 1000 && !justification) {
    g_form.showFieldMsg('business_justification',
      'Required for items over $1000', 'error');
    return false;
  }

  // Validate date is in future
  var neededBy = g_form.getValue('needed_by');
  var today = new GlideDateTime().getDate().getValue();
  if (neededBy < today) {
    g_form.showFieldMsg('needed_by',
      'Date must be in the future', 'error');
    return false;
  }

  return true;
}

Variable Sets

变量集

Creating Reusable Variable Sets

创建可复用的变量集

Variable Set: User Contact Information
├── contact_name (Single Line Text)
├── contact_email (Email)
├── contact_phone (Single Line Text)
└── preferred_contact (Choice: Email, Phone, Either)

Use in multiple catalog items:
- New Laptop Request
- Software Installation
- Network Access Request
Variable Set: User Contact Information
├── contact_name (Single Line Text)
├── contact_email (Email)
├── contact_phone (Single Line Text)
└── preferred_contact (Choice: Email, Phone, Either)

Use in multiple catalog items:
- New Laptop Request
- Software Installation
- Network Access Request

Accessing Variable Set Values

访问变量集的值

javascript
// In workflow or script
var ritm = current;  // sc_req_item

// Access variable from variable set
var contactEmail = ritm.variables.contact_email;
var preferredContact = ritm.variables.preferred_contact;
javascript
// In workflow or script
var ritm = current;  // sc_req_item

// Access variable from variable set
var contactEmail = ritm.variables.contact_email;
var preferredContact = ritm.variables.preferred_contact;

Catalog Workflows/Flows

目录工作流/流程

Approval Pattern

审批模式

Flow Trigger: sc_req_item created
├── If: Total cost > $5000
│   └── Request Approval: Department Manager
│   └── If: Rejected
│       └── Update: RITM state = Closed Incomplete
├── If: Total cost > $25000
│   └── Request Approval: VP
├── Create: Catalog Task for Fulfillment
└── Wait: Task completion
Flow Trigger: sc_req_item created
├── If: Total cost > $5000
│   └── Request Approval: Department Manager
│   └── If: Rejected
│       └── Update: RITM state = Closed Incomplete
├── If: Total cost > $25000
│   └── Request Approval: VP
├── Create: Catalog Task for Fulfillment
└── Wait: Task completion

Fulfillment Script

执行脚本

javascript
// In catalog item's "Execution Plan" or workflow

var ritm = current;  // sc_req_item

// Create an incident from catalog request
var inc = new GlideRecord('incident');
inc.initialize();
inc.setValue('short_description', ritm.short_description);
inc.setValue('description', ritm.description);
inc.setValue('caller_id', ritm.request.requested_for);
inc.setValue('category', ritm.variables.category);
inc.setValue('priority', ritm.variables.urgency);
inc.insert();

// Link incident to request
ritm.setValue('u_fulfillment_record', inc.getUniqueValue());
ritm.update();
javascript
// In catalog item's "Execution Plan" or workflow

var ritm = current;  // sc_req_item

// Create an incident from catalog request
var inc = new GlideRecord('incident');
inc.initialize();
inc.setValue('short_description', ritm.short_description);
inc.setValue('description', ritm.description);
inc.setValue('caller_id', ritm.request.requested_for);
inc.setValue('category', ritm.variables.category);
inc.setValue('priority', ritm.variables.urgency);
inc.insert();

// Link incident to request
ritm.setValue('u_fulfillment_record', inc.getUniqueValue());
ritm.update();

Record Producers

记录生成器

Creating Incidents via Catalog

通过目录创建事件

javascript
// Record Producer: Report an Issue
// Table: incident
// Script:

// Map variables to incident fields
current.short_description = producer.short_description;
current.description = producer.description;
current.caller_id = gs.getUserID();
current.category = producer.category;
current.subcategory = producer.subcategory;
current.priority = producer.urgency == 'urgent' ? '2' : '3';

// Set assignment based on category
if (producer.category == 'network') {
  current.assignment_group.setDisplayValue('Network Support');
} else {
  current.assignment_group.setDisplayValue('Service Desk');
}
javascript
// Record Producer: Report an Issue
// Table: incident
// Script:

// Map variables to incident fields
current.short_description = producer.short_description;
current.description = producer.description;
current.caller_id = gs.getUserID();
current.category = producer.category;
current.subcategory = producer.subcategory;
current.priority = producer.urgency == 'urgent' ? '2' : '3';

// Set assignment based on category
if (producer.category == 'network') {
  current.assignment_group.setDisplayValue('Network Support');
} else {
  current.assignment_group.setDisplayValue('Service Desk');
}

Order Guides

订购指南

Multi-Step Request Wizard

多步骤申请向导

Order Guide: New Employee Onboarding
├── Step 1: Employee Information
│   └── Variable Set: Employee Details
├── Step 2: Hardware Selection
│   ├── Catalog Item: Laptop
│   ├── Catalog Item: Monitor
│   └── Catalog Item: Peripherals
├── Step 3: Software Requests
│   └── Rule: Show software based on department
├── Step 4: Access Requests
│   └── Cascade Variable: Copy employee info
└── Submit: Creates multiple RITMs
Order Guide: New Employee Onboarding
├── Step 1: Employee Information
│   └── Variable Set: Employee Details
├── Step 2: Hardware Selection
│   ├── Catalog Item: Laptop
│   ├── Catalog Item: Monitor
│   └── Catalog Item: Peripherals
├── Step 3: Software Requests
│   └── Rule: Show software based on department
├── Step 4: Access Requests
│   └── Cascade Variable: Copy employee info
└── Submit: Creates multiple RITMs

Order Guide Rule

订购指南规则

javascript
// Rule: Show software items based on department
function rule(item, guide_variables) {
  var dept = guide_variables.department;

  // Show engineering software only for Engineering
  if (item.name == 'Engineering Software Suite') {
    return dept == 'engineering';
  }

  // Show finance software only for Finance
  if (item.name == 'Financial Tools') {
    return dept == 'finance';
  }

  return true;  // Show all other items
}
javascript
// Rule: Show software items based on department
function rule(item, guide_variables) {
  var dept = guide_variables.department;

  // Show engineering software only for Engineering
  if (item.name == 'Engineering Software Suite') {
    return dept == 'engineering';
  }

  // Show finance software only for Finance
  if (item.name == 'Financial Tools') {
    return dept == 'finance';
  }

  return true;  // Show all other items
}

Pricing & Approvals

定价与审批

Dynamic Pricing

动态定价

javascript
// Catalog Item Script (Pricing)
// Runs when item is added to cart

var basePrice = parseFloat(current.price) || 0;
var quantity = parseInt(current.variables.quantity) || 1;
var expedited = current.variables.expedited == 'true';

var total = basePrice * quantity;
if (expedited) {
  total *= 1.5;  // 50% rush fee
}

current.recurring_price = 0;
current.price = total;
javascript
// Catalog Item Script (Pricing)
// Runs when item is added to cart

var basePrice = parseFloat(current.price) || 0;
var quantity = parseInt(current.variables.quantity) || 1;
var expedited = current.variables.expedited == 'true';

var total = basePrice * quantity;
if (expedited) {
  total *= 1.5;  // 50% rush fee
}

current.recurring_price = 0;
current.price = total;

Approval Rules

审批规则

Approval Definition: High-Value Purchases
Condition: total_cost > 5000
Approver: requested_for.manager
Wait for: Approval
Rejection action: Cancel request
Approval Definition: High-Value Purchases
Condition: total_cost > 5000
Approver: requested_for.manager
Wait for: Approval
Rejection action: Cancel request

Best Practices

最佳实践

  1. Variable Naming - Use descriptive, lowercase names (no spaces)
  2. Variable Sets - Reuse common variable groups
  3. Reference Qualifiers - Filter to relevant records only
  4. Client Scripts - Minimize server calls (use GlideAjax sparingly)
  5. Fulfillment - Create tasks, don't complete directly
  6. Testing - Test as different user roles
  7. Mobile - Test catalog items on mobile/tablet
  8. Documentation - Add help text to variables
  1. 变量命名 - 使用描述性的小写名称(无空格)
  2. 变量集 - 复用通用变量组
  3. 引用限定符 - 仅过滤相关记录
  4. 客户端脚本 - 减少服务器调用(谨慎使用GlideAjax)
  5. 执行 - 创建任务,不要直接完成
  6. 测试 - 以不同用户角色测试
  7. 移动端 - 在手机/平板上测试目录项
  8. 文档 - 为变量添加帮助文本