Loading...
Loading...
This skill should be used when the user asks to "asset", "hardware asset", "software asset", "asset lifecycle", "inventory", "license management", "asset allocation", "HAM", "SAM", or any ServiceNow Asset Management development.
npx skill4agent add groeimetai/snow-flow asset-managementAsset (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 time| Table | Purpose |
|---|---|
| Base asset table |
| Hardware assets |
| Software licenses |
| Consumable assets |
| Asset contracts |
| Configuration items |
// 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 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') };
}// 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();// 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();
}// 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;
}// 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;
}| Tool | Purpose |
|---|---|
| Query assets and licenses |
| Search CMDB for CIs |
| Test asset scripts |
| Find asset configurations |
// 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'
});