Expense Report Processor
Validates expense amounts against policy, routes high-value expenses for manager approval.
switchemail
Source
/**
* Processes expense reports. Validates amounts, checks policy,
* and routes high-value expenses for manager approval.
*/
form expense_report {
label: "Expense Report"
schema: @json {
{
"type": "object",
"required": ["employee_email", "description", "amount", "category"],
"properties": {
"employee_email": { "type": "string", "format": "email", "title": "Your Email" },
"description": { "type": "string", "title": "Description" },
"amount": { "type": "number", "title": "Amount (USD)" },
"category": {
"type": "string",
"title": "Category",
"enum": ["travel", "meals", "software", "equipment", "other"]
},
"receipt_url": { "type": "string", "title": "Receipt URL" }
}
}
}
}
workflow process_expense {
label: "Process Expense"
root {
type: code
label: "Extract expense"
code: @ts { return context.nodes.root.input }
outputSchema: @json {
{
"type": "object",
"properties": {
"employee_email": { "type": "string" },
"description": { "type": "string" },
"amount": { "type": "number" },
"category": { "type": "string" },
"receipt_url": { "type": "string" }
}
}
}
}
node check_policy {
type: code
label: "Check policy limits"
code: @ts {
const expense = context.nodes.root.output
const limits = { travel: 500, meals: 100, software: 200, equipment: 1000, other: 250 }
const limit = limits[expense.category] || 250
const over_limit = expense.amount > limit
return {
amount: expense.amount,
category: expense.category,
limit: limit,
over_limit: over_limit,
needs_approval: expense.amount > 250
}
}
}
node route {
type: switch
label: "Route by amount"
cases: ["auto_approve", "needs_approval"]
router: @ts {
if (context.nodes.check_policy.output.needs_approval) return "needs_approval"
return "auto_approve"
}
}
node auto_approve {
type: code
label: "Auto-approve"
code: @ts {
return {
status: "approved",
employee: context.nodes.root.output.employee_email,
amount: context.nodes.root.output.amount,
category: context.nodes.root.output.category
}
}
}
node manager_review {
type: code
label: "Manager review"
code: @ts { return {} }
review: {
enabled: true
title: "Expense Approval Required"
description: "This expense exceeds the auto-approval threshold. See the check_policy node output for the expense details. Submit your decision; the employee is notified either way."
schema: @json {
{
"type": "object",
"required": ["approved"],
"properties": {
"approved": { "type": "boolean", "title": "Approved" },
"notes": { "type": "string", "title": "Notes" }
}
}
}
actions: [
{ id: "submit", label: "Submit Decision", outcome: "approve" }
]
}
}
node notify_employee {
type: email
label: "Notify employee"
from: @ts { return "[email protected]" }
to: @ts { return context.nodes.root.output.employee_email }
subject: @ts { return "Expense report update" }
text: @ts {
const expense = context.nodes.root.output
const review = context.reviews.manager_review || {}
const decision = review.approved ? "approved" : "denied"
const notes = review.notes ? "\n\nManager notes: " + review.notes : ""
return "Your expense report for $" + expense.amount + " (" + expense.category + ") has been " + decision + "." + notes
}
}
flow {
root -> check_policy
check_policy -> route
route -["auto_approve"]-> auto_approve
route -["needs_approval"]-> manager_review
manager_review -> notify_employee
}
}
trigger on_expense {
form:expense_report -> process_expense
enabled: true
}
Flow
Trigger to workflow
expense_reportform
process_expense
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Workflow nodes
CODE
Code Node
Extract expense
CODE
Code Node
Check policy limits
SWITCH
Switch Node
Route by amount
CODE
Code Node
Auto-approve
CODE
Code Node
Manager review
EMAIL
Email Node
Notify employee
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.