vendor-management
Vendor Management for ServiceNow
Vendor Management tracks suppliers, contracts, performance, and risk.
Vendor Architecture
Vendor (core_company)
├── Contracts (ast_contract)
│ ├── Contract Terms
│ └── SLAs
├── Contacts
├── Assessments
└── Performance Metrics
Key Tables
| Table | Purpose |
|---|---|
core_company |
Vendors/Companies |
ast_contract |
Contracts |
ast_contract_sla |
Contract SLAs |
vendor_risk_assessment |
Risk assessments |
procurement_vendor |
Vendor details |
Vendors (ES5)
Create Vendor
// Create vendor (ES5 ONLY!)
var vendor = new GlideRecord("core_company")
vendor.initialize()
// Basic info
vendor.setValue("name", "Acme Technology Solutions")
vendor.setValue("vendor", true)
// Contact info
vendor.setValue("phone", "+1-555-123-4567")
vendor.setValue("email", "vendor@acmetech.com")
vendor.setValue("website", "https://www.acmetech.com")
// Address
vendor.setValue("street", "456 Vendor Ave")
vendor.setValue("city", "San Francisco")
vendor.setValue("state", "CA")
vendor.setValue("zip", "94105")
vendor.setValue("country", "US")
// Classification
vendor.setValue("vendor_type", "technology")
vendor.setValue("u_vendor_tier", "strategic")
// Primary contact
vendor.setValue("contact", primaryContactSysId)
vendor.insert()
Vendor Search
// Search vendors (ES5 ONLY!)
function searchVendors(criteria) {
var vendors = []
var gr = new GlideRecord("core_company")
gr.addQuery("vendor", true)
gr.addQuery("vendor_active", true)
if (criteria.name) {
gr.addQuery("name", "CONTAINS", criteria.name)
}
if (criteria.type) {
gr.addQuery("vendor_type", criteria.type)
}
if (criteria.tier) {
gr.addQuery("u_vendor_tier", criteria.tier)
}
gr.query()
while (gr.next()) {
vendors.push({
sys_id: gr.getUniqueValue(),
name: gr.getValue("name"),
type: gr.getValue("vendor_type"),
tier: gr.getValue("u_vendor_tier"),
contact: gr.contact.getDisplayValue(),
active_contracts: countActiveContracts(gr.getUniqueValue()),
})
}
return vendors
}
function countActiveContracts(vendorSysId) {
var ga = new GlideAggregate("ast_contract")
ga.addQuery("vendor", vendorSysId)
ga.addQuery("state", "active")
ga.addAggregate("COUNT")
ga.query()
if (ga.next()) {
return parseInt(ga.getAggregate("COUNT"), 10)
}
return 0
}
Contracts (ES5)
Create Contract
// Create vendor contract (ES5 ONLY!)
var contract = new GlideRecord("ast_contract")
contract.initialize()
// Basic info
contract.setValue("short_description", "Cloud Hosting Services")
contract.setValue("vendor", vendorSysId)
contract.setValue("contract_model", "service_agreement")
// Dates
contract.setValue("starts", "2024-01-01")
contract.setValue("ends", "2025-12-31")
// Financial
contract.setValue("contract_value", 500000)
contract.setValue("payment_terms", "net_30")
contract.setValue("currency", "USD")
// Renewal
contract.setValue("renewal_type", "auto")
contract.setValue("renewal_notice_period", 90) // days
// Owner
contract.setValue("contract_administrator", adminSysId)
contract.setValue("stakeholders", stakeholderSysIds)
// Status
contract.setValue("state", "active")
contract.insert()
Contract Renewal Alert
// Find contracts expiring soon (ES5 ONLY!)
function getExpiringContracts(daysAhead) {
var expiringContracts = []
var futureDate = new GlideDateTime()
futureDate.addDaysLocalTime(daysAhead)
var contract = new GlideRecord("ast_contract")
contract.addQuery("state", "active")
contract.addQuery("ends", "<=", futureDate)
contract.addQuery("ends", ">=", new GlideDateTime())
contract.orderBy("ends")
contract.query()
while (contract.next()) {
expiringContracts.push({
sys_id: contract.getUniqueValue(),
number: contract.getValue("number"),
description: contract.getValue("short_description"),
vendor: contract.vendor.getDisplayValue(),
ends: contract.getValue("ends"),
value: contract.getValue("contract_value"),
renewal_type: contract.getValue("renewal_type"),
})
}
return expiringContracts
}
// Scheduled job to send alerts
;(function executeScheduledJob() {
var expiring = getExpiringContracts(90)
for (var i = 0; i < expiring.length; i++) {
var contract = new GlideRecord("ast_contract")
if (contract.get(expiring[i].sys_id)) {
gs.eventQueue("contract.expiring.soon", contract, "90", "")
}
}
})()
Contract SLAs (ES5)
Define Contract SLA
// Create contract SLA (ES5 ONLY!)
var sla = new GlideRecord("ast_contract_sla")
sla.initialize()
sla.setValue("contract", contractSysId)
sla.setValue("name", "Uptime Guarantee")
sla.setValue("description", "99.9% uptime guarantee")
// Metrics
sla.setValue("metric_type", "availability")
sla.setValue("target_value", "99.9")
sla.setValue("measurement_period", "monthly")
// Penalties/Credits
sla.setValue("penalty_type", "credit")
sla.setValue("penalty_description", "10% credit for each 0.1% below target")
sla.insert()
Track SLA Performance
// Record SLA measurement (ES5 ONLY!)
function recordSLAMeasurement(slaSysId, period, actualValue) {
var measurement = new GlideRecord("u_sla_measurement")
measurement.initialize()
measurement.setValue("sla", slaSysId)
measurement.setValue("period", period)
measurement.setValue("actual_value", actualValue)
measurement.setValue("measured_date", new GlideDateTime())
// Get target
var sla = new GlideRecord("ast_contract_sla")
if (sla.get(slaSysId)) {
var target = parseFloat(sla.getValue("target_value"))
var actual = parseFloat(actualValue)
measurement.setValue("target_value", target)
measurement.setValue("met", actual >= target)
if (actual < target) {
// Calculate penalty/credit
var shortfall = target - actual
measurement.setValue("shortfall", shortfall)
measurement.work_notes = "SLA not met. Shortfall: " + shortfall + "%"
}
}
return measurement.insert()
}
Vendor Risk Assessment (ES5)
Create Risk Assessment
// Create vendor risk assessment (ES5 ONLY!)
function createVendorAssessment(vendorSysId, assessmentData) {
var assessment = new GlideRecord("vendor_risk_assessment")
assessment.initialize()
assessment.setValue("vendor", vendorSysId)
assessment.setValue("assessment_date", new GlideDateTime())
assessment.setValue("assessor", gs.getUserID())
// Risk scores (1-5 scale)
assessment.setValue("financial_risk", assessmentData.financial)
assessment.setValue("operational_risk", assessmentData.operational)
assessment.setValue("security_risk", assessmentData.security)
assessment.setValue("compliance_risk", assessmentData.compliance)
assessment.setValue("strategic_risk", assessmentData.strategic)
// Calculate overall score
var scores = [
assessmentData.financial,
assessmentData.operational,
assessmentData.security,
assessmentData.compliance,
assessmentData.strategic,
]
var total = 0
for (var i = 0; i < scores.length; i++) {
total += parseInt(scores[i], 10)
}
var average = total / scores.length
assessment.setValue("overall_risk_score", average.toFixed(1))
// Risk rating
var rating = "low"
if (average >= 4) rating = "critical"
else if (average >= 3) rating = "high"
else if (average >= 2) rating = "medium"
assessment.setValue("risk_rating", rating)
// Notes
assessment.setValue("notes", assessmentData.notes)
return assessment.insert()
}
Vendor Performance Scorecard
// Calculate vendor performance score (ES5 ONLY!)
function getVendorScorecard(vendorSysId) {
var scorecard = {
vendor_sys_id: vendorSysId,
sla_performance: 0,
ticket_metrics: {},
risk_rating: "",
overall_score: 0,
}
// SLA performance
var slaMeasurements = new GlideAggregate("u_sla_measurement")
slaMeasurements.addQuery("sla.contract.vendor", vendorSysId)
slaMeasurements.addQuery("measured_date", ">=", gs.monthsAgo(12))
slaMeasurements.addAggregate("AVG", "met")
slaMeasurements.query()
if (slaMeasurements.next()) {
scorecard.sla_performance = Math.round(slaMeasurements.getAggregate("AVG", "met") * 100)
}
// Incident metrics
var incidents = new GlideAggregate("incident")
incidents.addQuery("vendor", vendorSysId)
incidents.addQuery("opened_at", ">=", gs.monthsAgo(12))
incidents.addAggregate("COUNT")
incidents.addAggregate("AVG", "calendar_duration")
incidents.query()
if (incidents.next()) {
scorecard.ticket_metrics.count = parseInt(incidents.getAggregate("COUNT"), 10)
scorecard.ticket_metrics.avg_resolution = incidents.getAggregate("AVG", "calendar_duration")
}
// Latest risk assessment
var assessment = new GlideRecord("vendor_risk_assessment")
assessment.addQuery("vendor", vendorSysId)
assessment.orderByDesc("assessment_date")
assessment.setLimit(1)
assessment.query()
if (assessment.next()) {
scorecard.risk_rating = assessment.getValue("risk_rating")
}
// Calculate overall score
scorecard.overall_score = calculateOverallScore(scorecard)
return scorecard
}
MCP Tool Integration
Available Tools
| Tool | Purpose |
|---|---|
snow_query_table |
Query vendor tables |
snow_execute_script_with_output |
Test vendor scripts |
snow_find_artifact |
Find configurations |
Example Workflow
// 1. Query active vendors
await snow_query_table({
table: "core_company",
query: "vendor=true^vendor_active=true",
fields: "name,vendor_type,u_vendor_tier,contact",
})
// 2. Find expiring contracts
await snow_execute_script_with_output({
script: `
var expiring = getExpiringContracts(60);
gs.info(JSON.stringify(expiring));
`,
})
// 3. Get vendor scorecard
await snow_execute_script_with_output({
script: `
var scorecard = getVendorScorecard('vendor_sys_id');
gs.info(JSON.stringify(scorecard));
`,
})
Best Practices
- Vendor Classification - Tier by importance
- Contract Tracking - Monitor expirations
- SLA Monitoring - Track performance
- Risk Assessment - Regular evaluations
- Performance Reviews - Quarterly scorecards
- Documentation - Complete records
- Compliance - Verify certifications
- ES5 Only - No modern JavaScript syntax
More from groeimetai/snow-flow
knowledge-management
This skill should be used when the user asks to "create knowledge article", "KB article", "knowledge base", "knowledge workflow", "article template", "publish article", or any ServiceNow Knowledge Management development.
87reporting-dashboards
This skill should be used when the user asks to "create report", "dashboard", "chart", "visualization", "analytics", "scheduled report", "export data", or any ServiceNow reporting and dashboard development.
77document-management
This skill should be used when the user asks to "attachment", "document", "file upload", "document template", "PDF generation", "document workflow", or any ServiceNow Document Management development.
74predictive-intelligence
This skill should be used when the user asks to "predictive intelligence", "machine learning", "ML", "classification", "similarity", "clustering", "prediction", "AI", or any ServiceNow Predictive Intelligence development.
72mcp-tool-discovery
This skill should be used when the user asks about "available tools", "what tools", "how to find tools", "tool search", "MCP servers", "list tools", "discover tools", "which tools", or needs guidance on discovering and using Snow-Flow MCP tools.
68email-notifications
This skill should be used when the user asks to "create notification", "email notification", "send email", "notification script", "email template", "sysevent_email_action", "notify user", "alert", or any ServiceNow email and notification development.
67