asset-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAsset Management for ServiceNow
ServiceNow 资产管理
Asset Management tracks hardware and software assets throughout their lifecycle.
资产管理模块用于全程跟踪硬件和软件资产的生命周期。
Asset Architecture
资产架构
Asset (alm_asset)
├── Hardware Asset (alm_hardware)
│ └── Consumable (alm_consumable)
└── License (alm_license)
CI (cmdb_ci) ←→ Asset (alm_asset)
↑
One CI can have multiple assets over timeAsset (alm_asset)
├── Hardware Asset (alm_hardware)
│ └── Consumable (alm_consumable)
└── License (alm_license)
CI (cmdb_ci) ←→ Asset (alm_asset)
↑
One CI can have multiple assets over timeKey Tables
核心表
| Table | Purpose |
|---|---|
| Base asset table |
| Hardware assets |
| Software licenses |
| Consumable assets |
| Asset contracts |
| Configuration items |
| 表名 | 用途 |
|---|---|
| 资产基础表 |
| 硬件资产表 |
| 软件许可证表 |
| 消耗品资产表 |
| 资产合同表 |
| 配置项表 |
Hardware Assets (ES5)
硬件资产(ES5)
Create Hardware Asset
创建硬件资产
javascript
// Create hardware asset (ES5 ONLY!)
var asset = new GlideRecord('alm_hardware');
asset.initialize();
// Basic info
asset.setValue('display_name', 'Dell Latitude 5520');
asset.setValue('asset_tag', 'ASSET-' + generateAssetTag());
asset.setValue('serial_number', 'SN123456789');
// Model
asset.setValue('model', getModelSysId('Dell Latitude 5520'));
asset.setValue('model_category', getModelCategorySysId('Laptop'));
// Status and substatus
asset.setValue('install_status', 1); // Installed
asset.setValue('substatus', 'in_use');
// Assignment
asset.setValue('assigned_to', userSysId);
asset.setValue('assigned', new GlideDateTime());
asset.setValue('location', locationSysId);
asset.setValue('department', departmentSysId);
// Financial
asset.setValue('cost', 1299.99);
asset.setValue('cost_center', costCenterSysId);
// Dates
asset.setValue('purchase_date', '2024-01-15');
asset.setValue('warranty_expiration', '2027-01-15');
// Link to CI if exists
asset.setValue('ci', cmdbCiSysId);
asset.insert();javascript
// Create hardware asset (ES5 ONLY!)
var asset = new GlideRecord('alm_hardware');
asset.initialize();
// Basic info
asset.setValue('display_name', 'Dell Latitude 5520');
asset.setValue('asset_tag', 'ASSET-' + generateAssetTag());
asset.setValue('serial_number', 'SN123456789');
// Model
asset.setValue('model', getModelSysId('Dell Latitude 5520'));
asset.setValue('model_category', getModelCategorySysId('Laptop'));
// Status and substatus
asset.setValue('install_status', 1); // Installed
asset.setValue('substatus', 'in_use');
// Assignment
asset.setValue('assigned_to', userSysId);
asset.setValue('assigned', new GlideDateTime());
asset.setValue('location', locationSysId);
asset.setValue('department', departmentSysId);
// Financial
asset.setValue('cost', 1299.99);
asset.setValue('cost_center', costCenterSysId);
// Dates
asset.setValue('purchase_date', '2024-01-15');
asset.setValue('warranty_expiration', '2027-01-15');
// Link to CI if exists
asset.setValue('ci', cmdbCiSysId);
asset.insert();Asset Lifecycle States
资产生命周期状态
javascript
// Asset install_status values
var ASSET_STATUS = {
INSTALLED: 1, // In use
ON_ORDER: 2, // Ordered, not received
IN_STOCK: 6, // In inventory
IN_TRANSIT: 7, // Being shipped
IN_MAINTENANCE: 8, // Under repair
RETIRED: 9, // End of life
DISPOSED: 10 // Disposed of
};
// Transition asset status (ES5 ONLY!)
function transitionAssetStatus(assetSysId, newStatus, notes) {
var asset = new GlideRecord('alm_hardware');
if (!asset.get(assetSysId)) {
return { success: false, message: 'Asset not found' };
}
var currentStatus = parseInt(asset.getValue('install_status'), 10);
// Validate transition
var validTransitions = {
2: [6, 7], // On Order -> In Stock, In Transit
7: [6, 1], // In Transit -> In Stock, Installed
6: [1, 7, 9], // In Stock -> Installed, In Transit, Retired
1: [8, 6, 9], // Installed -> In Maintenance, In Stock, Retired
8: [1, 6, 9], // In Maintenance -> Installed, In Stock, Retired
9: [10] // Retired -> Disposed
};
if (!validTransitions[currentStatus] ||
validTransitions[currentStatus].indexOf(newStatus) === -1) {
return {
success: false,
message: 'Invalid transition from ' + currentStatus + ' to ' + newStatus
};
}
// Update status
asset.setValue('install_status', newStatus);
// Handle specific transitions
if (newStatus === 1) {
asset.setValue('installed', new GlideDateTime());
} else if (newStatus === 9) {
asset.setValue('retired', new GlideDateTime());
asset.setValue('assigned_to', '');
} else if (newStatus === 10) {
asset.setValue('disposed', new GlideDateTime());
}
// Add work note
if (notes) {
asset.work_notes = notes;
}
asset.update();
return { success: true, asset_tag: asset.getValue('asset_tag') };
}javascript
// Asset install_status values
var ASSET_STATUS = {
INSTALLED: 1, // In use
ON_ORDER: 2, // Ordered, not received
IN_STOCK: 6, // In inventory
IN_TRANSIT: 7, // Being shipped
IN_MAINTENANCE: 8, // Under repair
RETIRED: 9, // End of life
DISPOSED: 10 // Disposed of
};
// Transition asset status (ES5 ONLY!)
function transitionAssetStatus(assetSysId, newStatus, notes) {
var asset = new GlideRecord('alm_hardware');
if (!asset.get(assetSysId)) {
return { success: false, message: 'Asset not found' };
}
var currentStatus = parseInt(asset.getValue('install_status'), 10);
// Validate transition
var validTransitions = {
2: [6, 7], // On Order -> In Stock, In Transit
7: [6, 1], // In Transit -> In Stock, Installed
6: [1, 7, 9], // In Stock -> Installed, In Transit, Retired
1: [8, 6, 9], // Installed -> In Maintenance, In Stock, Retired
8: [1, 6, 9], // In Maintenance -> Installed, In Stock, Retired
9: [10] // Retired -> Disposed
};
if (!validTransitions[currentStatus] ||
validTransitions[currentStatus].indexOf(newStatus) === -1) {
return {
success: false,
message: 'Invalid transition from ' + currentStatus + ' to ' + newStatus
};
}
// Update status
asset.setValue('install_status', newStatus);
// Handle specific transitions
if (newStatus === 1) {
asset.setValue('installed', new GlideDateTime());
} else if (newStatus === 9) {
asset.setValue('retired', new GlideDateTime());
asset.setValue('assigned_to', '');
} else if (newStatus === 10) {
asset.setValue('disposed', new GlideDateTime());
}
// Add work note
if (notes) {
asset.work_notes = notes;
}
asset.update();
return { success: true, asset_tag: asset.getValue('asset_tag') };
}Software Licenses (ES5)
软件许可证(ES5)
Create License Record
创建许可证记录
javascript
// Create software license (ES5 ONLY!)
var license = new GlideRecord('alm_license');
license.initialize();
// Basic info
license.setValue('display_name', 'Microsoft Office 365 E3');
license.setValue('product', getProductSysId('Microsoft Office 365'));
license.setValue('license_type', 'per_user'); // per_user, per_device, site, enterprise
// Quantities
license.setValue('rights', 500); // Total licenses purchased
license.setValue('used', 0); // Will be calculated
license.setValue('remaining', 500); // Will be calculated
// Dates
license.setValue('start_date', '2024-01-01');
license.setValue('end_date', '2024-12-31');
// Cost
license.setValue('cost', 25000.00);
license.setValue('cost_per_unit', 50.00);
// Vendor
license.setValue('vendor', vendorSysId);
license.setValue('contract', contractSysId);
license.insert();javascript
// Create software license (ES5 ONLY!)
var license = new GlideRecord('alm_license');
license.initialize();
// Basic info
license.setValue('display_name', 'Microsoft Office 365 E3');
license.setValue('product', getProductSysId('Microsoft Office 365'));
license.setValue('license_type', 'per_user'); // per_user, per_device, site, enterprise
// Quantities
license.setValue('rights', 500); // Total licenses purchased
license.setValue('used', 0); // Will be calculated
license.setValue('remaining', 500); // Will be calculated
// Dates
license.setValue('start_date', '2024-01-01');
license.setValue('end_date', '2024-12-31');
// Cost
license.setValue('cost', 25000.00);
license.setValue('cost_per_unit', 50.00);
// Vendor
license.setValue('vendor', vendorSysId);
license.setValue('contract', contractSysId);
license.insert();License Allocation
许可证分配
javascript
// Allocate license to user (ES5 ONLY!)
function allocateLicense(licenseSysId, userSysId) {
var license = new GlideRecord('alm_license');
if (!license.get(licenseSysId)) {
return { success: false, message: 'License not found' };
}
// Check availability
var remaining = parseInt(license.getValue('remaining'), 10);
if (remaining <= 0) {
return { success: false, message: 'No licenses available' };
}
// Check if user already has this license
var existing = new GlideRecord('alm_entitlement_user');
existing.addQuery('licensed_by', licenseSysId);
existing.addQuery('user', userSysId);
existing.query();
if (existing.hasNext()) {
return { success: false, message: 'User already has this license' };
}
// Create entitlement
var entitlement = new GlideRecord('alm_entitlement_user');
entitlement.initialize();
entitlement.setValue('licensed_by', licenseSysId);
entitlement.setValue('user', userSysId);
entitlement.setValue('allocated', new GlideDateTime());
entitlement.insert();
// Update license counts
updateLicenseCounts(licenseSysId);
return {
success: true,
message: 'License allocated',
entitlement: entitlement.getUniqueValue()
};
}
function updateLicenseCounts(licenseSysId) {
var license = new GlideRecord('alm_license');
if (!license.get(licenseSysId)) return;
// Count allocations
var ga = new GlideAggregate('alm_entitlement_user');
ga.addQuery('licensed_by', licenseSysId);
ga.addAggregate('COUNT');
ga.query();
var used = 0;
if (ga.next()) {
used = parseInt(ga.getAggregate('COUNT'), 10);
}
var rights = parseInt(license.getValue('rights'), 10);
license.setValue('used', used);
license.setValue('remaining', rights - used);
license.update();
}javascript
// Allocate license to user (ES5 ONLY!)
function allocateLicense(licenseSysId, userSysId) {
var license = new GlideRecord('alm_license');
if (!license.get(licenseSysId)) {
return { success: false, message: 'License not found' };
}
// Check availability
var remaining = parseInt(license.getValue('remaining'), 10);
if (remaining <= 0) {
return { success: false, message: 'No licenses available' };
}
// Check if user already has this license
var existing = new GlideRecord('alm_entitlement_user');
existing.addQuery('licensed_by', licenseSysId);
existing.addQuery('user', userSysId);
existing.query();
if (existing.hasNext()) {
return { success: false, message: 'User already has this license' };
}
// Create entitlement
var entitlement = new GlideRecord('alm_entitlement_user');
entitlement.initialize();
entitlement.setValue('licensed_by', licenseSysId);
entitlement.setValue('user', userSysId);
entitlement.setValue('allocated', new GlideDateTime());
entitlement.insert();
// Update license counts
updateLicenseCounts(licenseSysId);
return {
success: true,
message: 'License allocated',
entitlement: entitlement.getUniqueValue()
};
}
function updateLicenseCounts(licenseSysId) {
var license = new GlideRecord('alm_license');
if (!license.get(licenseSysId)) return;
// Count allocations
var ga = new GlideAggregate('alm_entitlement_user');
ga.addQuery('licensed_by', licenseSysId);
ga.addAggregate('COUNT');
ga.query();
var used = 0;
if (ga.next()) {
used = parseInt(ga.getAggregate('COUNT'), 10);
}
var rights = parseInt(license.getValue('rights'), 10);
license.setValue('used', used);
license.setValue('remaining', rights - used);
license.update();
}Asset Discovery Integration (ES5)
资产发现集成(ES5)
Match Discovered CI to Asset
将发现的CI匹配到资产
javascript
// Match discovered CI to existing asset (ES5 ONLY!)
function matchCIToAsset(ciSysId) {
var ci = new GlideRecord('cmdb_ci_computer');
if (!ci.get(ciSysId)) {
return null;
}
var serialNumber = ci.getValue('serial_number');
var assetTag = ci.getValue('asset_tag');
// Try to find matching asset
var asset = new GlideRecord('alm_hardware');
// Match by serial number first
if (serialNumber) {
asset.addQuery('serial_number', serialNumber);
asset.query();
if (asset.next()) {
return linkAssetToCI(asset, ci);
}
}
// Match by asset tag
if (assetTag) {
asset = new GlideRecord('alm_hardware');
asset.addQuery('asset_tag', assetTag);
asset.query();
if (asset.next()) {
return linkAssetToCI(asset, ci);
}
}
// No match - create new asset
return createAssetFromCI(ci);
}
function linkAssetToCI(asset, ci) {
asset.setValue('ci', ci.getUniqueValue());
asset.update();
ci.setValue('asset', asset.getUniqueValue());
ci.update();
return asset.getUniqueValue();
}
function createAssetFromCI(ci) {
var asset = new GlideRecord('alm_hardware');
asset.initialize();
asset.setValue('display_name', ci.getDisplayValue());
asset.setValue('serial_number', ci.getValue('serial_number'));
asset.setValue('asset_tag', ci.getValue('asset_tag'));
asset.setValue('model', ci.getValue('model_id'));
asset.setValue('ci', ci.getUniqueValue());
asset.setValue('install_status', 1);
var assetSysId = asset.insert();
ci.setValue('asset', assetSysId);
ci.update();
return assetSysId;
}javascript
// Match discovered CI to existing asset (ES5 ONLY!)
function matchCIToAsset(ciSysId) {
var ci = new GlideRecord('cmdb_ci_computer');
if (!ci.get(ciSysId)) {
return null;
}
var serialNumber = ci.getValue('serial_number');
var assetTag = ci.getValue('asset_tag');
// Try to find matching asset
var asset = new GlideRecord('alm_hardware');
// Match by serial number first
if (serialNumber) {
asset.addQuery('serial_number', serialNumber);
asset.query();
if (asset.next()) {
return linkAssetToCI(asset, ci);
}
}
// Match by asset tag
if (assetTag) {
asset = new GlideRecord('alm_hardware');
asset.addQuery('asset_tag', assetTag);
asset.query();
if (asset.next()) {
return linkAssetToCI(asset, ci);
}
}
// No match - create new asset
return createAssetFromCI(ci);
}
function linkAssetToCI(asset, ci) {
asset.setValue('ci', ci.getUniqueValue());
asset.update();
ci.setValue('asset', asset.getUniqueValue());
ci.update();
return asset.getUniqueValue();
}
function createAssetFromCI(ci) {
var asset = new GlideRecord('alm_hardware');
asset.initialize();
asset.setValue('display_name', ci.getDisplayValue());
asset.setValue('serial_number', ci.getValue('serial_number'));
asset.setValue('asset_tag', ci.getValue('asset_tag'));
asset.setValue('model', ci.getValue('model_id'));
asset.setValue('ci', ci.getUniqueValue());
asset.setValue('install_status', 1);
var assetSysId = asset.insert();
ci.setValue('asset', assetSysId);
ci.update();
return assetSysId;
}Asset Reports (ES5)
资产报表(ES5)
Asset Inventory Summary
资产库存汇总
javascript
// Get asset inventory summary (ES5 ONLY!)
function getAssetInventorySummary() {
var summary = {
by_status: {},
by_category: {},
by_location: {},
total_value: 0
};
// By status
var ga = new GlideAggregate('alm_hardware');
ga.addAggregate('COUNT');
ga.addAggregate('SUM', 'cost');
ga.groupBy('install_status');
ga.query();
while (ga.next()) {
var status = ga.install_status.getDisplayValue();
summary.by_status[status] = {
count: parseInt(ga.getAggregate('COUNT'), 10),
value: parseFloat(ga.getAggregate('SUM', 'cost')) || 0
};
summary.total_value += summary.by_status[status].value;
}
// By model category
ga = new GlideAggregate('alm_hardware');
ga.addAggregate('COUNT');
ga.groupBy('model_category');
ga.query();
while (ga.next()) {
var category = ga.model_category.getDisplayValue() || 'Uncategorized';
summary.by_category[category] = parseInt(ga.getAggregate('COUNT'), 10);
}
// By location
ga = new GlideAggregate('alm_hardware');
ga.addQuery('install_status', 1); // Only installed
ga.addAggregate('COUNT');
ga.groupBy('location');
ga.query();
while (ga.next()) {
var location = ga.location.getDisplayValue() || 'Unknown';
summary.by_location[location] = parseInt(ga.getAggregate('COUNT'), 10);
}
return summary;
}javascript
// Get asset inventory summary (ES5 ONLY!)
function getAssetInventorySummary() {
var summary = {
by_status: {},
by_category: {},
by_location: {},
total_value: 0
};
// By status
var ga = new GlideAggregate('alm_hardware');
ga.addAggregate('COUNT');
ga.addAggregate('SUM', 'cost');
ga.groupBy('install_status');
ga.query();
while (ga.next()) {
var status = ga.install_status.getDisplayValue();
summary.by_status[status] = {
count: parseInt(ga.getAggregate('COUNT'), 10),
value: parseFloat(ga.getAggregate('SUM', 'cost')) || 0
};
summary.total_value += summary.by_status[status].value;
}
// By model category
ga = new GlideAggregate('alm_hardware');
ga.addAggregate('COUNT');
ga.groupBy('model_category');
ga.query();
while (ga.next()) {
var category = ga.model_category.getDisplayValue() || 'Uncategorized';
summary.by_category[category] = parseInt(ga.getAggregate('COUNT'), 10);
}
// By location
ga = new GlideAggregate('alm_hardware');
ga.addQuery('install_status', 1); // Only installed
ga.addAggregate('COUNT');
ga.groupBy('location');
ga.query();
while (ga.next()) {
var location = ga.location.getDisplayValue() || 'Unknown';
summary.by_location[location] = parseInt(ga.getAggregate('COUNT'), 10);
}
return summary;
}MCP Tool Integration
MCP工具集成
Available Tools
可用工具
| Tool | Purpose |
|---|---|
| Query assets and licenses |
| Search CMDB for CIs |
| Test asset scripts |
| Find asset configurations |
| 工具 | 用途 |
|---|---|
| 查询资产和许可证 |
| 在CMDB中搜索配置项 |
| 测试资产脚本 |
| 查找资产配置 |
Example Workflow
示例工作流
javascript
// 1. Query hardware assets
await snow_query_table({
table: 'alm_hardware',
query: 'install_status=1',
fields: 'asset_tag,display_name,assigned_to,location,model'
});
// 2. Check license compliance
await snow_execute_script_with_output({
script: `
var license = new GlideRecord('alm_license');
license.addQuery('remainingRELATIVELT@integer@0');
license.query();
while (license.next()) {
gs.info('Over-allocated: ' + license.display_name);
}
`
});
// 3. Find assets nearing warranty expiration
await snow_query_table({
table: 'alm_hardware',
query: 'warranty_expirationBETWEENjavascript:gs.beginningOfToday()@javascript:gs.daysAgoEnd(-30)',
fields: 'asset_tag,display_name,warranty_expiration,assigned_to'
});javascript
// 1. Query hardware assets
await snow_query_table({
table: 'alm_hardware',
query: 'install_status=1',
fields: 'asset_tag,display_name,assigned_to,location,model'
});
// 2. Check license compliance
await snow_execute_script_with_output({
script: `
var license = new GlideRecord('alm_license');
license.addQuery('remainingRELATIVELT@integer@0');
license.query();
while (license.next()) {
gs.info('Over-allocated: ' + license.display_name);
}
`
});
// 3. Find assets nearing warranty expiration
await snow_query_table({
table: 'alm_hardware',
query: 'warranty_expirationBETWEENjavascript:gs.beginningOfToday()@javascript:gs.daysAgoEnd(-30)',
fields: 'asset_tag,display_name,warranty_expiration,assigned_to'
});Best Practices
最佳实践
- Asset Tags - Unique, scannable identifiers
- Lifecycle Tracking - Track all state changes
- CI Linking - Connect assets to CMDB
- License Compliance - Monitor allocation vs rights
- Warranty Tracking - Alert before expiration
- Financial Accuracy - Maintain cost data
- Regular Audits - Verify physical inventory
- ES5 Only - No modern JavaScript syntax
- 资产标签 - 唯一、可扫描的标识符
- 生命周期跟踪 - 跟踪所有状态变更
- CI关联 - 将资产与CMDB关联
- 许可证合规性 - 监控分配量与授权量
- 保修跟踪 - 在到期前触发提醒
- 财务准确性 - 维护成本数据
- 定期审计 - 核实实物库存
- 仅支持ES5 - 不使用现代JavaScript语法