catalog-items について
ServiceNow の開発者向けサービスカタログスキルです。カタログ項目、変数、クライアントスクリプト、承認、履行を説明し、レコードプロデューサーやオーダーガイドの例も含みます。
主な機能
- 01カタログ、カテゴリ、申請項目の設計
- 02変数と再利用可能な変数セットの設定
- 03クライアントスクリプトとフォーム検証の作成
- 04価格、承認、履行フローの設定
- 05レコードプロデューサーとオーダーガイドの作成
活用シーン
- 01セルフサービス申請フォームの構築
- 02複数のカタログ項目で項目グループを再利用
- 03条件に応じた申請検証と価格計算
- 04複数項目を含む入社申請ウィザードの作成
MCP 対応
README では、snow_create_variable と snow_create_catalog_variable など、カタログ変数を作成する MCP ツールに触れています。
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill catalog-itemsインストール後、Claude Code で/catalog-itemsを入力して読み込まれたか確認します。
詳細
ServiceNow のサービスカタログ開発
サービスカタログでは、セルフサービスポータルを通じてユーザーがサービスやアイテムをリクエストできます。
カタログの構成要素
| 構成要素 | 目的 | 例 |
|---|---|---|
| カタログ | カテゴリのコンテナー | IT サービスカタログ |
| カテゴリ | アイテムのグループ | ハードウェア、ソフトウェア |
| アイテム | リクエスト可能なサービス | 新しいノート PC のリクエスト |
| 変数 | アイテム上のフォームフィールド | ノート PC モデルのドロップダウン |
| 変数セット | 再利用可能な変数グループ | ユーザー詳細 |
| プロデューサー | レコードを直接作成します | インシデントの報告 |
| オーダーガイド | 複数アイテムのウィザード | 新入社員のセットアップ |
カタログアイテムの構造
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
変数の種類
| 種類 | 使用例 | 例 |
|---|---|---|
| 単一行テキスト | 短い入力 | 従業員 ID |
| 複数行テキスト | 長い入力 | 業務上の正当な理由 |
| 選択ボックス | 単一選択 | 優先度 |
| チェックボックス | はい/いいえ | 速達配送 |
| 参照 | テーブルへのリンク | リクエスト対象者 |
| 日付 | 日付ピッカー | 必要日付 |
| ルックアップ選択ボックス | フィルターされた参照 | カテゴリ別のモデル |
| リストコレクター | 複数選択 | CC 受信者 |
| コンテナー開始/終了 | 視覚的なグループ化 | ハードウェアオプション |
| マクロ | カスタムウィジェット | コスト計算ツール |
カタログ変数の作成
基本的な変数
// Via MCP (snow_create_variable supports reference, checkbox, etc.;
// snow_create_catalog_variable covers text/choice types only)
snow_create_variable({
cat_item: "<catalog item sys_id>",
name: "laptop_model",
question_text: "Laptop Model",
type: "reference",
mandatory: true,
order: 100,
})
// Set the reference table and qualifier on the created variable
snow_record_manage({
action: "update",
table: "item_option_new",
sys_id: "<variable sys_id>",
data: { reference: "cmdb_model", reference_qual: "category=computer" },
})
動的なデフォルト値を持つ変数
// Variable: requested_for
// Type: Reference (sys_user)
// Default value (script):
javascript: gs.getUserID()
参照修飾子を持つ変数
// 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
カタログクライアントスクリプト
onLoad 時にデフォルト値を設定
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())
}
onChange 時に価格を動的に設定
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))
}
onSubmit 時に検証
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 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
変数セットの値へのアクセス
// 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
カタログのワークフロー/フロー
承認パターン
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
フルフィルメントスクリプト
// 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 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 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
オーダーガイドのルール
// 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
}
価格設定と承認
動的な価格設定
// 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 Definition: High-Value Purchases
Condition: total_cost > 5000
Approver: requested_for.manager
Wait for: Approval
Rejection action: Cancel request
ベストプラクティス
- 変数の命名 - わかりやすい小文字の名前を使用します(スペースなし)
- 変数セット - 共通の変数グループを再利用します
- 参照修飾子 - 関連するレコードのみをフィルターします
- クライアントスクリプト - サーバー呼び出しを最小限に抑えます(GlideAjax は控えめに使用します)
- フルフィルメント - タスクを作成し、直接完了しないようにします
- テスト - 異なるユーザーロールでテストします
- モバイル - カタログアイテムをモバイル/タブレットでテストします
- ドキュメント - 変数にヘルプテキストを追加します
コメント
Markdown 対応