Complete Example: Leave Request System

This complete example demonstrates how to build an employee leave request system using forms, workflows, and ETL integration.

System Overview

What it does: - Employees submit leave requests via a form - Requests are routed to managers for approval - Approved requests go to HR for final approval - Email notifications sent at each step - Complete audit trail maintained - Leave balance tracked and updated

Components: - Leave request form (data entry) - Leave approval workflow (state management) - Validation ETL chain (business rules) - Notification ETL chains (emails) - Processing ETL chain (data updates)

Step 1: Create the Form

Form Structure

Leave Request Form
├── root
│   ├── Label: "Leave Request"
│   ├── Validator: leave-request-validation
│   └── Label Mode: Vertical
├── page1 (Main Request)
│   └── column1
│       ├── text-input (employeeName)
│       │   ├── Label: "Employee Name"
│       │   ├── Default Value: ${username}
│       │   ├── Disabled: true
│       │   └── Mandatory: true
│       ├── select (leaveType)
│       │   ├── Label: "Leave Type"
│       │   ├── Choices:
│       │   │   ├── annual: "Annual Leave"
│       │   │   ├── sick: "Sick Leave"
│       │   │   ├── personal: "Personal Leave"
│       │   │   └── unpaid: "Unpaid Leave"
│       │   └── Mandatory: true
│       ├── date-input (startDate)
│       │   ├── Label: "Start Date"
│       │   └── Mandatory: true
│       ├── date-input (endDate)
│       │   ├── Label: "End Date"
│       │   └── Mandatory: true
│       ├── text-area (reason)
│       │   ├── Label: "Reason"
│       │   ├── Rows: 4
│       │   └── Mandatory: true
│       ├── attachments (documents)
│       │   ├── Label: "Supporting Documents"
│       │   └── Mandatory: false
│       └── button-bar
│           └── Submit Button
├── page2 (Manager Approval)
│   └── column2
│       ├── html (requestSummary)
│       │   └── Display request details
│       ├── text-area (managerComments)
│       │   ├── Label: "Manager Comments"
│       │   └── Mandatory: false
│       └── button-bar
│           ├── Approve Button
│           └── Reject Button
├── page3 (HR Approval)
│   └── column3
│       ├── html (requestSummary)
│       │   └── Display request details
│       ├── text-area (hrComments)
│       │   ├── Label: "HR Comments"
│       │   └── Mandatory: false
│       └── button-bar
│           ├── Approve Button
│           └── Reject Button
├── page4 (Status View)
│   └── column4
│       ├── html (statusDisplay)
│       │   └── Show current status
│       ├── history (approvalHistory)
│       │   └── Display workflow history
│       └── button-bar
│           └── Close Button
├── workflow-state
│   ├── Workflow Id: leave-approval-workflow
│   └── Event: Submit
└── hidden (currentState)
    └── Value: ${elxPublic.currentState}

Form Designer Steps

  1. Create the form:
  • Go to Forms page
  • Click Add
  • Name: “Leave Request”
  • Select Blank Form
  1. Add Page 1 (Employee Request):
  • Drag Page onto root
  • Add Column to page
  • Add Text Input: employeeName
    • Default Value: ${username}
    • Disabled: true
  • Add Select: leaveType
    • Add choices (annual, sick, personal, unpaid)
  • Add Date Input: startDate
  • Add Date Input: endDate
  • Add Text Area: reason
  • Add Attachments: documents
  • Add Button Bar with Submit
  1. Add Page 2 (Manager Approval):
  • Drag Page onto root
  • Add Column
  • Add HTML: requestSummary (display request details)
  • Add Text Area: managerComments
  • Add Button Bar with Approve/Reject buttons
  1. Add Page 3 (HR Approval):
  • Similar to Page 2
  • Add Text Area: hrComments
  • Add Button Bar with Approve/Reject buttons
  1. Add Page 4 (Status View):
  • Add Column
  • Add HTML: statusDisplay
  • Add History component
  • Add Button Bar with Close button
  1. Add Workflow State:
  • Drag Workflow State onto root
  • Select workflow: leave-approval-workflow
  • Event: Submit
  1. Add Hidden Field:
  • Drag Hidden onto root
  • Id: currentState
  • Value: ${elxPublic.currentState}

Step 2: Create Form Rules

Rule 1: Show Page 1 for New Requests

Rule: Show Employee Request Page
├── Conditions:
│   └── currentState == "" OR currentState == "Draft"
├── Actions:
│   ├── Show: page1
│   ├── Hide: page2
│   ├── Hide: page3
│   └── Hide: page4
└── Enabled: true

Rule 2: Show Page 2 for Manager Approval

Rule: Show Manager Approval Page
├── Conditions:
│   ├── currentState == "Manager Approval"
│   └── ${roles} contains "Manager"
├── Actions:
│   ├── Hide: page1
│   ├── Show: page2
│   ├── Hide: page3
│   └── Hide: page4
└── Enabled: true

Rule 3: Show Page 3 for HR Approval

Rule: Show HR Approval Page
├── Conditions:
│   ├── currentState == "HR Approval"
│   └── ${roles} contains "HR"
├── Actions:
│   ├── Hide: page1
│   ├── Hide: page2
│   ├── Show: page3
│   └── Hide: page4
└── Enabled: true

Rule 4: Show Page 4 for Status View

Rule: Show Status Page
├── Conditions:
│   └── currentState == "Approved" OR currentState == "Rejected"
├── Actions:
│   ├── Hide: page1
│   ├── Hide: page2
│   ├── Hide: page3
│   └── Show: page4
└── Enabled: true

Rule 5: Mandatory Medical Certificate for Sick Leave

Rule: Require Medical Certificate
├── Conditions:
│   └── leaveType == "sick"
├── Actions:
│   └── Make Mandatory: documents
└── Enabled: true

Step 3: Create Validation ETL Chain

Chainset: leave-request-validation

Purpose: Validate leave request before submission

Chain: Validate Leave Request
├── Step 1: Check Date Range
│   ├── Get startDate and endDate
│   ├── Verify endDate > startDate
│   └── If invalid, add validation issue
│
├── Step 2: Check Future Dates
│   ├── Get startDate
│   ├── Verify startDate >= today
│   └── If invalid, add validation issue
│
├── Step 3: Check Leave Balance
│   ├── Get employeeName and leaveType
│   ├── Query leave balance database
│   ├── Calculate requested days
│   ├── Verify balance >= requested days
│   └── If insufficient, add validation issue
│
├── Step 4: Check Blackout Dates
│   ├── Get startDate and endDate
│   ├── Query blackout dates
│   ├── Check for overlap
│   └── If overlap, add validation issue
│
├── Step 5: Check Medical Certificate
│   ├── If leaveType == "sick"
│   ├── Verify documents attached
│   └── If missing, add validation issue
│
└── Step 6: Validation Endpoint
    └── Marker step

Validation Issues Format:

{
  "validationIssues": [
    {
      "field": "endDate",
      "message": "End date must be after start date"
    },
    {
      "field": "startDate",
      "message": "Start date cannot be in the past"
    },
    {
      "field": "leaveType",
      "message": "Insufficient leave balance (5 days requested, 3 days available)"
    }
  ]
}

Step 4: Create the Workflow

Workflow: leave-approval-workflow

Leave Approval Workflow
├── State: Draft
│   └── Transition: Submit → Manager Approval
│       ├── OnTransition ETL: calculate-leave-days
│       └── Event: Submit
│
├── State: Manager Approval
│   ├── OnEntry ETL: notify-manager
│   ├── Transition: Approve → HR Approval
│   │   ├── Guard: check-manager-is-approver
│   │   └── Event: Approve
│   └── Transition: Reject → Rejected
│       ├── Guard: check-manager-is-approver
│       └── Event: Reject
│
├── State: HR Approval
│   ├── OnEntry ETL: notify-hr
│   ├── Transition: Approve → Approved
│   │   ├── Guard: check-hr-role
│   │   └── Event: Approve
│   └── Transition: Reject → Rejected
│       ├── Guard: check-hr-role
│       └── Event: Reject
│
├── State: Approved
│   ├── OnEntry ETL: process-approval
│   └── Final state
│
└── State: Rejected
    ├── OnEntry ETL: process-rejection
    └── Final state

Step 5: Create ETL Chains for Workflow

Chain: calculate-leave-days

Trigger: OnTransition from Draft to Manager Approval

Calculate Leave Days
├── Step 1: Get start and end dates from elxPublic
├── Step 2: Calculate business days between dates
├── Step 3: Subtract holidays
├── Step 4: Store result in elxPublic.calculatedDays
└── Step 5: Continue workflow

Chain: notify-manager

Trigger: OnEntry to Manager Approval state

Notify Manager
├── Step 1: Get employee name from elxPublic
├── Step 2: Lookup manager from org chart
│   └── Query: SELECT manager FROM employees WHERE name = ?
├── Step 3: Store manager ID in elxPrivate.managerId
├── Step 4: Get manager email
├── Step 5: Compose email
│   ├── To: manager email
│   ├── Subject: "Leave Request from ${employeeName}"
│   └── Body: Include request details and approval link
├── Step 6: Send email
└── Step 7: Log notification

Chain: check-manager-is-approver

Trigger: Guard for Approve/Reject transitions

Check Manager Authorization
├── Step 1: Get current user ID
├── Step 2: Get manager ID from elxPrivate.managerId
├── Step 3: Compare user ID to manager ID
├── Step 4: Return true if match, false otherwise
└── If false, transition blocked

Chain: notify-hr

Trigger: OnEntry to HR Approval state

Notify HR
├── Step 1: Get request details from elxPublic
├── Step 2: Query HR team members
├── Step 3: For each HR member
│   ├── Compose email
│   └── Send notification
└── Step 4: Log notifications

Chain: check-hr-role

Trigger: Guard for HR Approve/Reject

Check HR Authorization
├── Step 1: Get current user roles
├── Step 2: Check if "HR" role present
├── Step 3: Return true if HR, false otherwise
└── If false, transition blocked

Chain: process-approval

Trigger: OnEntry to Approved state

Process Approval
├── Step 1: Get leave details from elxPublic
├── Step 2: Update leave balance database
│   └── Deduct calculated days from balance
├── Step 3: Create calendar entry
│   ├── Title: "${employeeName} - ${leaveType}"
│   ├── Start: startDate
│   └── End: endDate
├── Step 4: Notify employee
│   ├── Compose approval email
│   └── Send to employee
├── Step 5: Set redirect URL
│   └── elxRedirect: "/dashboard/my-leave"
└── Step 6: Log approval

Chain: process-rejection

Trigger: OnEntry to Rejected state

Process Rejection
├── Step 1: Get rejection details
│   ├── From elxPublic.managerComments or elxPublic.hrComments
│   └── Store reason
├── Step 2: Notify employee
│   ├── Compose rejection email
│   ├── Include rejection reason
│   └── Send to employee
├── Step 3: Set redirect URL
│   └── elxRedirect: "/dashboard/my-leave"
└── Step 4: Log rejection

Step 6: Configure Form Properties

  1. Root Properties:
  • Label: “Leave Request”
  • Validator: leave-request-validation
  • Label Mode: Vertical
  • Scroll To Error: true
  1. Workflow State Properties:
  • Workflow Id: leave-approval-workflow
  • Event: Submit

Step 7: Test the System

Test as Employee

  1. Open the form
  2. Fill in leave details
  3. Attach medical certificate (if sick leave)
  4. Click Submit
  5. Verify validation works
  6. Verify workflow instance created
  7. Verify redirect to status page

Test as Manager

  1. Receive email notification
  2. Click link to open form
  3. See Page 2 (Manager Approval)
  4. Review request details
  5. Add comments
  6. Click Approve or Reject
  7. Verify transition to next state

Test as HR

  1. Receive email notification
  2. Click link to open form
  3. See Page 3 (HR Approval)
  4. Review request and manager comments
  5. Add HR comments
  6. Click Approve or Reject
  7. Verify final state reached

Test Status View

  1. Open approved/rejected request
  2. See Page 4 (Status View)
  3. Verify history displays all transitions
  4. Verify status is clear
  5. Click Close

Step 8: Query Form Results

ETL Chain: Get Approved Leave Requests

Get Approved Requests
├── Step 1: form.ReadFormResults
│   ├── formId: "leave-request"
│   ├── filter: {"elxPublic.currentState": "Approved"}
│   ├── sort: {"elxPublic.startDate": 1}
│   └── limit: 100
├── Step 2: Extract relevant fields
├── Step 3: Format for display
└── Step 4: Return results

Generate Leave Report

Generate Monthly Leave Report
├── Step 1: form.ReadFormResults
│   ├── formId: "leave-request"
│   └── filter: {
│       "elxPublic.currentState": "Approved",
│       "elxPublic.startDate": {
│         "$gte": "2026-03-01",
│         "$lt": "2026-04-01"
│       }
│     }
├── Step 2: Group by department
├── Step 3: Calculate totals
├── Step 4: Generate report
└── Step 5: Email to management

Complete Data Flow

1. Employee opens form
   ↓
2. Form loads with Page 1 visible
   ↓
3. Employee fills details
   ↓
4. Employee clicks Submit
   ↓
5. Client validation (mandatory fields)
   ↓
6. Server validation (ETL chain)
   ↓
7. Workflow instance created (Draft state)
   ↓
8. Submit event sent to workflow
   ↓
9. Transition: Draft → Manager Approval
   ↓
10. calculate-leave-days ETL runs
    ↓
11. notify-manager ETL runs
    ↓
12. Manager receives email
    ↓
13. Manager opens form (Page 2 visible)
    ↓
14. Manager clicks Approve
    ↓
15. check-manager-is-approver guard runs
    ↓
16. Transition: Manager Approval → HR Approval
    ↓
17. notify-hr ETL runs
    ↓
18. HR receives email
    ↓
19. HR opens form (Page 3 visible)
    ↓
20. HR clicks Approve
    ↓
21. check-hr-role guard runs
    ↓
22. Transition: HR Approval → Approved
    ↓
23. process-approval ETL runs
    ↓
24. Leave balance updated
    ↓
25. Calendar entry created
    ↓
26. Employee notified
    ↓
27. Form redirects to dashboard

Enhancements

Add Auto-Approval for Short Leave

Modify workflow to auto-approve leave < 2 days:

State: Draft
├── Transition: Submit → Auto-Approved
│   ├── Guard: check-short-leave (days < 2)
│   └── Event: Submit
└── Transition: Submit → Manager Approval
    ├── Guard: check-long-leave (days >= 2)
    └── Event: Submit

Add Escalation for Overdue Approvals

Add deferred event to Manager Approval state:

State: Manager Approval
├── OnAfter: 2 days
│   └── Send escalation email to manager's manager
└── OnAfter: 4 days
    └── Auto-approve and notify

Add Leave Balance Display

Add to form:

Column
├── html (leaveBalance)
│   └── Display: "Available: ${elxPublic.availableLeave} days"
└── Script: Load balance on form load

Summary

This complete example demonstrates: - Multi-page form with conditional display - Workflow integration with state management - ETL validation with business rules - ETL processing at workflow transitions - Email notifications - Guard conditions for authorization - Audit trail with history - Form results querying - Role-based UI with rules

The system provides a complete, production-ready leave request solution with approval workflow, validation, notifications, and reporting.