重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
hr-service-delivery by groeimetai/snow-flow
npx skills add https://github.com/groeimetai/snow-flow --skill hr-service-delivery人力资源服务交付(HRSD)通过案例、生命周期事件和自助服务简化员工服务。
Employee Center (Portal)
├── HR Service Catalog
│ ├── HR Catalog Items
│ └── Requests → HR Cases
├── Knowledge Articles
└── My HR Cases
HR Cases (sn_hr_core_case)
├── Case Tasks
├── Lifecycle Events
└── Document Requests
| 表 | 用途 |
|---|---|
sn_hr_core_case | HR 案例 |
sn_hr_core_case_operation | 案例操作/任务 |
sn_hr_le_lifecycle_event | 生命周期事件 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
sn_hr_le_activity | 生命周期活动 |
sn_hr_core_service | HR 服务 |
// Create HR Case (ES5 ONLY!)
var hrCase = new GlideRecord("sn_hr_core_case")
hrCase.initialize()
// Case details
hrCase.setValue("short_description", "Request for salary verification letter")
hrCase.setValue("description", "Employee needs salary verification for mortgage application")
// HR Service and Category
hrCase.setValue("hr_service", getHRService("Document Requests"))
hrCase.setValue("hr_service_type", "general_inquiry")
// Subject person (employee)
hrCase.setValue("subject_person", employeeSysId)
hrCase.setValue("opened_for", employeeSysId)
// Opened by (could be different - e.g., manager on behalf)
hrCase.setValue("opened_by", gs.getUserID())
// Assignment
hrCase.setValue("assignment_group", getGroupSysId("HR Operations"))
// Priority
hrCase.setValue("priority", 3)
var caseSysId = hrCase.insert()
// Process HR catalog request (ES5 ONLY!)
// Called from HR Catalog Item workflow
;(function executeActivity(inputs, outputs, scratchpad) {
// Get request item details
var ritm = inputs.request_item
var variables = ritm.variables
// Create HR Case
var hrCase = new GlideRecord("sn_hr_core_case")
hrCase.initialize()
hrCase.setValue("short_description", ritm.cat_item.getDisplayValue() + " for " + ritm.opened_for.getDisplayValue())
hrCase.setValue("hr_service", ritm.cat_item.u_hr_service)
hrCase.setValue("subject_person", ritm.opened_for)
hrCase.setValue("opened_for", ritm.opened_for)
hrCase.setValue("opened_by", ritm.opened_by)
// Copy variables to case
hrCase.setValue("u_effective_date", variables.effective_date)
hrCase.setValue("u_reason", variables.reason)
// Link to request
hrCase.setValue("parent", ritm.getUniqueValue())
outputs.hr_case = hrCase.insert()
})(inputs, outputs, scratchpad)
// Create onboarding lifecycle event (ES5 ONLY!)
function createOnboardingEvent(employeeSysId, startDate, details) {
var lifecycle = new GlideRecord("sn_hr_le_lifecycle_event")
lifecycle.initialize()
// Event details
lifecycle.setValue("name", "Onboarding - " + getEmployeeName(employeeSysId))
lifecycle.setValue("subject_person", employeeSysId)
lifecycle.setValue("state", "ready") // ready, in_progress, complete
// Lifecycle event type
lifecycle.setValue("le_type", getLifecycleType("onboarding"))
// Dates
lifecycle.setValue("planned_start", startDate)
// Copy details
lifecycle.setValue("department", details.department)
lifecycle.setValue("location", details.location)
lifecycle.setValue("manager", details.manager)
var eventSysId = lifecycle.insert()
// Generate activities from template
generateActivitiesFromTemplate(eventSysId, "onboarding")
return eventSysId
}
// Generate lifecycle activities from template (ES5 ONLY!)
function generateActivitiesFromTemplate(lifecycleEventSysId, templateName) {
// Get lifecycle event
var lifecycleEvent = new GlideRecord("sn_hr_le_lifecycle_event")
if (!lifecycleEvent.get(lifecycleEventSysId)) {
return
}
// Get template activities
var template = new GlideRecord("sn_hr_le_activity_template")
template.addQuery("template", templateName)
template.orderBy("order")
template.query()
var plannedStart = new GlideDateTime(lifecycleEvent.getValue("planned_start"))
while (template.next()) {
var activity = new GlideRecord("sn_hr_le_activity")
activity.initialize()
// Link to lifecycle event
activity.setValue("lifecycle_event", lifecycleEventSysId)
// Copy from template
activity.setValue("short_description", template.getValue("name"))
activity.setValue("description", template.getValue("description"))
activity.setValue("activity_type", template.getValue("activity_type"))
activity.setValue("assignment_group", template.getValue("assignment_group"))
// Calculate due date based on offset
var dueDate = new GlideDateTime(plannedStart)
dueDate.addDaysLocalTime(parseInt(template.getValue("day_offset"), 10))
activity.setValue("due_date", dueDate)
// Set order
activity.setValue("order", template.getValue("order"))
// State
activity.setValue("state", "pending")
activity.insert()
}
}
// Trigger offboarding lifecycle event (ES5 ONLY!)
// Business Rule: after, update, sys_user
;(function executeRule(current, previous) {
// Check if employee is being terminated
if (current.active.changesTo(false) && current.u_employment_status.changesTo("terminated")) {
createOffboardingEvent(current)
}
})(current, previous)
function createOffboardingEvent(user) {
var lifecycle = new GlideRecord("sn_hr_le_lifecycle_event")
lifecycle.initialize()
lifecycle.setValue("name", "Offboarding - " + user.getDisplayValue())
lifecycle.setValue("subject_person", user.getUniqueValue())
lifecycle.setValue("le_type", getLifecycleType("offboarding"))
lifecycle.setValue("state", "ready")
lifecycle.setValue("planned_start", user.getValue("u_termination_date") || new GlideDateTime())
// Capture current access for revocation
lifecycle.setValue("u_current_groups", getCurrentGroups(user.getUniqueValue()))
lifecycle.setValue("u_current_roles", getCurrentRoles(user.getUniqueValue()))
var eventSysId = lifecycle.insert()
// Generate offboarding activities
generateActivitiesFromTemplate(eventSysId, "offboarding")
// Notify HR and Manager
gs.eventQueue("hr.offboarding.initiated", lifecycle, user.manager, "")
}
// Create HR Service (ES5 ONLY!)
var service = new GlideRecord("sn_hr_core_service")
service.initialize()
service.setValue("name", "Benefits Enrollment")
service.setValue("short_description", "Enroll in or change benefit plans")
service.setValue("description", "Request enrollment or changes to health, dental, vision, and retirement benefits")
// Category
service.setValue("topic", getHRTopic("Benefits"))
// Fulfillment
service.setValue("fulfillment_group", getGroupSysId("Benefits Administration"))
service.setValue("default_sla", getSLASysId("HR Standard Response"))
// Access control
service.setValue("visibility", "all_employees") // all_employees, specific_criteria
// Enable for Employee Center
service.setValue("employee_center_visible", true)
service.insert()
// Generate HR document (ES5 ONLY!)
function generateHRDocument(hrCaseSysId, documentType) {
var hrCase = new GlideRecord("sn_hr_core_case")
if (!hrCase.get(hrCaseSysId)) {
return null
}
var employee = hrCase.subject_person.getRefRecord()
// Get document template
var template = new GlideRecord("sn_hr_core_document_template")
template.addQuery("name", documentType)
template.query()
if (!template.next()) {
gs.error("Document template not found: " + documentType)
return null
}
// Process template with employee data
var content = template.getValue("template_body")
content = processTemplate(content, {
employee_name: employee.getDisplayValue(),
employee_id: employee.getValue("employee_number"),
title: employee.getValue("title"),
department: employee.department.getDisplayValue(),
start_date: employee.getValue("u_start_date"),
salary: employee.getValue("u_annual_salary"),
manager_name: employee.manager.getDisplayValue(),
current_date: new GlideDateTime().getLocalDate().toString(),
})
// Create document record
var doc = new GlideRecord("sn_hr_core_document")
doc.initialize()
doc.setValue("hr_case", hrCaseSysId)
doc.setValue("subject_person", employee.getUniqueValue())
doc.setValue("document_type", documentType)
doc.setValue("name", documentType + " - " + employee.getDisplayValue())
doc.setValue("content", content)
doc.setValue("state", "draft")
return doc.insert()
}
function processTemplate(template, data) {
for (var key in data) {
if (data.hasOwnProperty(key)) {
var pattern = new RegExp("\\{\\{" + key + "\\}\\}", "g")
template = template.replace(pattern, data[key] || "")
}
}
return template
}
// Widget Server Script - HR Case Status (ES5 ONLY!)
;(function () {
var userId = gs.getUserID()
// Get user's HR cases
data.cases = []
var gr = new GlideRecord("sn_hr_core_case")
gr.addQuery("subject_person", userId)
gr.addQuery("active", true)
gr.orderByDesc("opened_at")
gr.setLimit(10)
gr.query()
while (gr.next()) {
data.cases.push({
sys_id: gr.getUniqueValue(),
number: gr.getValue("number"),
short_description: gr.getValue("short_description"),
state: gr.state.getDisplayValue(),
priority: gr.priority.getDisplayValue(),
opened_at: gr.getValue("opened_at"),
hr_service: gr.hr_service.getDisplayValue(),
})
}
// Get pending activities for user
data.activities = []
var activity = new GlideRecord("sn_hr_le_activity")
activity.addQuery("lifecycle_event.subject_person", userId)
activity.addQuery("state", "IN", "pending,in_progress")
activity.orderBy("due_date")
activity.query()
while (activity.next()) {
data.activities.push({
sys_id: activity.getUniqueValue(),
short_description: activity.getValue("short_description"),
due_date: activity.getValue("due_date"),
state: activity.state.getDisplayValue(),
})
}
})()
| 工具 | 用途 |
|---|---|
snow_query_table | 查询 HR 案例和活动 |
snow_find_artifact | 查找 HR 配置 |
snow_execute_script_with_output | 测试 HR 脚本 |
snow_deploy | 部署 HR 小部件 |
// 1. Query open HR cases
await snow_query_table({
table: "sn_hr_core_case",
query: "active=true^assignment_group=HR Operations",
fields: "number,short_description,subject_person,state,opened_at",
})
// 2. Find lifecycle events
await snow_query_table({
table: "sn_hr_le_lifecycle_event",
query: "state=in_progress",
fields: "name,subject_person,le_type,planned_start",
})
// 3. Create HR case
await snow_execute_script_with_output({
script: `
var hrCase = new GlideRecord('sn_hr_core_case');
hrCase.initialize();
hrCase.short_description = 'Test HR Case';
hrCase.subject_person = gs.getUserID();
gs.info('Created: ' + hrCase.insert());
`,
})
每周安装次数
52
代码仓库
GitHub 星标数
58
首次出现
2026年1月22日
安全审计
已安装于
gemini-cli47
claude-code47
github-copilot46
cursor46
opencode46
codex46
HR Service Delivery (HRSD) streamlines employee services through cases, lifecycle events, and self-service.
Employee Center (Portal)
├── HR Service Catalog
│ ├── HR Catalog Items
│ └── Requests → HR Cases
├── Knowledge Articles
└── My HR Cases
HR Cases (sn_hr_core_case)
├── Case Tasks
├── Lifecycle Events
└── Document Requests
| Table | Purpose |
|---|---|
sn_hr_core_case | HR cases |
sn_hr_core_case_operation | Case operations/tasks |
sn_hr_le_lifecycle_event | Lifecycle events |
sn_hr_le_activity | Lifecycle activities |
sn_hr_core_service | HR services |
// Create HR Case (ES5 ONLY!)
var hrCase = new GlideRecord("sn_hr_core_case")
hrCase.initialize()
// Case details
hrCase.setValue("short_description", "Request for salary verification letter")
hrCase.setValue("description", "Employee needs salary verification for mortgage application")
// HR Service and Category
hrCase.setValue("hr_service", getHRService("Document Requests"))
hrCase.setValue("hr_service_type", "general_inquiry")
// Subject person (employee)
hrCase.setValue("subject_person", employeeSysId)
hrCase.setValue("opened_for", employeeSysId)
// Opened by (could be different - e.g., manager on behalf)
hrCase.setValue("opened_by", gs.getUserID())
// Assignment
hrCase.setValue("assignment_group", getGroupSysId("HR Operations"))
// Priority
hrCase.setValue("priority", 3)
var caseSysId = hrCase.insert()
// Process HR catalog request (ES5 ONLY!)
// Called from HR Catalog Item workflow
;(function executeActivity(inputs, outputs, scratchpad) {
// Get request item details
var ritm = inputs.request_item
var variables = ritm.variables
// Create HR Case
var hrCase = new GlideRecord("sn_hr_core_case")
hrCase.initialize()
hrCase.setValue("short_description", ritm.cat_item.getDisplayValue() + " for " + ritm.opened_for.getDisplayValue())
hrCase.setValue("hr_service", ritm.cat_item.u_hr_service)
hrCase.setValue("subject_person", ritm.opened_for)
hrCase.setValue("opened_for", ritm.opened_for)
hrCase.setValue("opened_by", ritm.opened_by)
// Copy variables to case
hrCase.setValue("u_effective_date", variables.effective_date)
hrCase.setValue("u_reason", variables.reason)
// Link to request
hrCase.setValue("parent", ritm.getUniqueValue())
outputs.hr_case = hrCase.insert()
})(inputs, outputs, scratchpad)
// Create onboarding lifecycle event (ES5 ONLY!)
function createOnboardingEvent(employeeSysId, startDate, details) {
var lifecycle = new GlideRecord("sn_hr_le_lifecycle_event")
lifecycle.initialize()
// Event details
lifecycle.setValue("name", "Onboarding - " + getEmployeeName(employeeSysId))
lifecycle.setValue("subject_person", employeeSysId)
lifecycle.setValue("state", "ready") // ready, in_progress, complete
// Lifecycle event type
lifecycle.setValue("le_type", getLifecycleType("onboarding"))
// Dates
lifecycle.setValue("planned_start", startDate)
// Copy details
lifecycle.setValue("department", details.department)
lifecycle.setValue("location", details.location)
lifecycle.setValue("manager", details.manager)
var eventSysId = lifecycle.insert()
// Generate activities from template
generateActivitiesFromTemplate(eventSysId, "onboarding")
return eventSysId
}
// Generate lifecycle activities from template (ES5 ONLY!)
function generateActivitiesFromTemplate(lifecycleEventSysId, templateName) {
// Get lifecycle event
var lifecycleEvent = new GlideRecord("sn_hr_le_lifecycle_event")
if (!lifecycleEvent.get(lifecycleEventSysId)) {
return
}
// Get template activities
var template = new GlideRecord("sn_hr_le_activity_template")
template.addQuery("template", templateName)
template.orderBy("order")
template.query()
var plannedStart = new GlideDateTime(lifecycleEvent.getValue("planned_start"))
while (template.next()) {
var activity = new GlideRecord("sn_hr_le_activity")
activity.initialize()
// Link to lifecycle event
activity.setValue("lifecycle_event", lifecycleEventSysId)
// Copy from template
activity.setValue("short_description", template.getValue("name"))
activity.setValue("description", template.getValue("description"))
activity.setValue("activity_type", template.getValue("activity_type"))
activity.setValue("assignment_group", template.getValue("assignment_group"))
// Calculate due date based on offset
var dueDate = new GlideDateTime(plannedStart)
dueDate.addDaysLocalTime(parseInt(template.getValue("day_offset"), 10))
activity.setValue("due_date", dueDate)
// Set order
activity.setValue("order", template.getValue("order"))
// State
activity.setValue("state", "pending")
activity.insert()
}
}
// Trigger offboarding lifecycle event (ES5 ONLY!)
// Business Rule: after, update, sys_user
;(function executeRule(current, previous) {
// Check if employee is being terminated
if (current.active.changesTo(false) && current.u_employment_status.changesTo("terminated")) {
createOffboardingEvent(current)
}
})(current, previous)
function createOffboardingEvent(user) {
var lifecycle = new GlideRecord("sn_hr_le_lifecycle_event")
lifecycle.initialize()
lifecycle.setValue("name", "Offboarding - " + user.getDisplayValue())
lifecycle.setValue("subject_person", user.getUniqueValue())
lifecycle.setValue("le_type", getLifecycleType("offboarding"))
lifecycle.setValue("state", "ready")
lifecycle.setValue("planned_start", user.getValue("u_termination_date") || new GlideDateTime())
// Capture current access for revocation
lifecycle.setValue("u_current_groups", getCurrentGroups(user.getUniqueValue()))
lifecycle.setValue("u_current_roles", getCurrentRoles(user.getUniqueValue()))
var eventSysId = lifecycle.insert()
// Generate offboarding activities
generateActivitiesFromTemplate(eventSysId, "offboarding")
// Notify HR and Manager
gs.eventQueue("hr.offboarding.initiated", lifecycle, user.manager, "")
}
// Create HR Service (ES5 ONLY!)
var service = new GlideRecord("sn_hr_core_service")
service.initialize()
service.setValue("name", "Benefits Enrollment")
service.setValue("short_description", "Enroll in or change benefit plans")
service.setValue("description", "Request enrollment or changes to health, dental, vision, and retirement benefits")
// Category
service.setValue("topic", getHRTopic("Benefits"))
// Fulfillment
service.setValue("fulfillment_group", getGroupSysId("Benefits Administration"))
service.setValue("default_sla", getSLASysId("HR Standard Response"))
// Access control
service.setValue("visibility", "all_employees") // all_employees, specific_criteria
// Enable for Employee Center
service.setValue("employee_center_visible", true)
service.insert()
// Generate HR document (ES5 ONLY!)
function generateHRDocument(hrCaseSysId, documentType) {
var hrCase = new GlideRecord("sn_hr_core_case")
if (!hrCase.get(hrCaseSysId)) {
return null
}
var employee = hrCase.subject_person.getRefRecord()
// Get document template
var template = new GlideRecord("sn_hr_core_document_template")
template.addQuery("name", documentType)
template.query()
if (!template.next()) {
gs.error("Document template not found: " + documentType)
return null
}
// Process template with employee data
var content = template.getValue("template_body")
content = processTemplate(content, {
employee_name: employee.getDisplayValue(),
employee_id: employee.getValue("employee_number"),
title: employee.getValue("title"),
department: employee.department.getDisplayValue(),
start_date: employee.getValue("u_start_date"),
salary: employee.getValue("u_annual_salary"),
manager_name: employee.manager.getDisplayValue(),
current_date: new GlideDateTime().getLocalDate().toString(),
})
// Create document record
var doc = new GlideRecord("sn_hr_core_document")
doc.initialize()
doc.setValue("hr_case", hrCaseSysId)
doc.setValue("subject_person", employee.getUniqueValue())
doc.setValue("document_type", documentType)
doc.setValue("name", documentType + " - " + employee.getDisplayValue())
doc.setValue("content", content)
doc.setValue("state", "draft")
return doc.insert()
}
function processTemplate(template, data) {
for (var key in data) {
if (data.hasOwnProperty(key)) {
var pattern = new RegExp("\\{\\{" + key + "\\}\\}", "g")
template = template.replace(pattern, data[key] || "")
}
}
return template
}
// Widget Server Script - HR Case Status (ES5 ONLY!)
;(function () {
var userId = gs.getUserID()
// Get user's HR cases
data.cases = []
var gr = new GlideRecord("sn_hr_core_case")
gr.addQuery("subject_person", userId)
gr.addQuery("active", true)
gr.orderByDesc("opened_at")
gr.setLimit(10)
gr.query()
while (gr.next()) {
data.cases.push({
sys_id: gr.getUniqueValue(),
number: gr.getValue("number"),
short_description: gr.getValue("short_description"),
state: gr.state.getDisplayValue(),
priority: gr.priority.getDisplayValue(),
opened_at: gr.getValue("opened_at"),
hr_service: gr.hr_service.getDisplayValue(),
})
}
// Get pending activities for user
data.activities = []
var activity = new GlideRecord("sn_hr_le_activity")
activity.addQuery("lifecycle_event.subject_person", userId)
activity.addQuery("state", "IN", "pending,in_progress")
activity.orderBy("due_date")
activity.query()
while (activity.next()) {
data.activities.push({
sys_id: activity.getUniqueValue(),
short_description: activity.getValue("short_description"),
due_date: activity.getValue("due_date"),
state: activity.state.getDisplayValue(),
})
}
})()
| Tool | Purpose |
|---|---|
snow_query_table | Query HR cases and activities |
snow_find_artifact | Find HR configurations |
snow_execute_script_with_output | Test HR scripts |
snow_deploy | Deploy HR widgets |
// 1. Query open HR cases
await snow_query_table({
table: "sn_hr_core_case",
query: "active=true^assignment_group=HR Operations",
fields: "number,short_description,subject_person,state,opened_at",
})
// 2. Find lifecycle events
await snow_query_table({
table: "sn_hr_le_lifecycle_event",
query: "state=in_progress",
fields: "name,subject_person,le_type,planned_start",
})
// 3. Create HR case
await snow_execute_script_with_output({
script: `
var hrCase = new GlideRecord('sn_hr_core_case');
hrCase.initialize();
hrCase.short_description = 'Test HR Case';
hrCase.subject_person = gs.getUserID();
gs.info('Created: ' + hrCase.insert());
`,
})
Weekly Installs
52
Repository
GitHub Stars
58
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli47
claude-code47
github-copilot46
cursor46
opencode46
codex46
AI 驱动绩效评估工具:生成自我/经理评估模板,支持校准准备
590 周安装
GitHub Actions 智能工作流自动化:AI多智能体协调优化CI/CD流水线
63 周安装
.NET 8 升级 .NET 9 迁移指南:解决破坏性变更,更新目标框架至 net9.0
123 周安装
Excel财务建模与数据分析指南:专业模板、零错误公式与颜色编码标准
106 周安装
piglet Python代码审查指南:遵循《Python工匠》模式的代码质量提升工具
57 周安装
Seedance 2.0 四模态AI电影制作:文生视频、图生视频、视频生视频、参考视频生视频
60 周安装
Prowler UI测试指南:Playwright最佳实践与E2E测试规范
52 周安装