Managing employee expense reimbursements is a classic business use case β and a perfect fit for Oracle APEX Workflows. In this blog, weβll build a real-world, end-to-end Expense Reimbursement Workflow where small expenses are auto-approved and larger ones require manager approval.
By the end of this guide, youβll have:
- An automated approval flow
- Conditional logic (auto vs manual approval)
- Human tasks for managers
- Email notifications
- A working submission form
Letβs dive in π
π§© Workflow Scenario
Business Rules:
- An employee submits an expense claim
- If the amount is less than $100 β β Auto-approved
- If the amount is $100 or more β π¨βπΌ Manager approval required
- If approved β πΈ Payment is processed
- If rejected β π§ Employee is notified
π§ Part 1: Prerequisites β Database Setup
Before creating the workflow, we need a table to store expense claims.
Run the following SQL in SQL Workshop:
CREATE TABLE expense_claims (
claim_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
employee_name VARCHAR2(100),
employee_email VARCHAR2(100),
expense_type VARCHAR2(50), -- Travel, Meals, Hardware
amount NUMBER,
description VARCHAR2(4000),
status VARCHAR2(20), -- SUBMITTED, APPROVED, REJECTED, PAID
submitted_date TIMESTAMP WITH LOCAL TIME ZONE DEFAULT SYSTIMESTAMP
);This table will be the backbone of our workflow.
π Part 2: Creating the Workflow
Navigation:
Shared Components β Workflows and Automations β Workflows β Create
Workflow Details:
- Name: Expense Reimbursement
- Static ID: EXP_REIMB
- Version: 1.0
- Title: Expense Claim for &EMPLOYEE_NAME.
Delete the default Execute Code activity so you start with a clean slate.

π¦ Part 3: Defining Data (Parameters & Variables)
1οΈβ£ Workflow Parameters (Inputs)
Create the following parameters:

| Label | Static ID | Data Type | Purpose |
|---|---|---|---|
| Employee Name | EMPLOYEE_NAME | VARCHAR2 | Display & routing |
| Employee Email | EMPLOYEE_EMAIL | VARCHAR2 | Notifications |
| Amount | AMOUNT | NUMBER | Approval logic |
| Claim ID | CLAIM_ID | NUMBER | DB row reference |
2οΈβ£ Workflow Variables (Internal Logic)
Create these variables:

| Name | Static ID | Data Type | Purpose |
|---|---|---|---|
| Task Outcome | TASK_OUTCOME | VARCHAR2 | APPROVED / REJECTED |
| Approver | APPROVER | VARCHAR2 | Who approved |
π Part 4: Auto-Approval Logic (Switch Activity)
Weβll automatically approve low-value expenses.

Steps:
- Drag a Switch activity after Start
- Name it: Check Amount
- Type: PL/SQL Expression
- Expression:
:AMOUNT < 100Branches:
- True β Auto-Approve (skip manager)
- False β Manager approval required
π¨βπΌ Part 5: Creating the Human Task (Manager Approval)
Before adding a Human Task to the workflow, define it.
Task Definition
Navigation:
Shared Components β Task Definitions β Create
Settings:
- Name: Manager Approval
- Subject: Expense Approval for &EMPLOYEE_NAME. ($&AMOUNT.)
- Priority: Medium
Participants:
- Type: Potential Owner
- Value: admin (or role/user)
Actions Source (SQL):
select * from expense_claims where claim_id = :APEX$TASK_PK;Task Parameters:
- AMOUNT
- DESCRIPTION
- EXPENSE_TYPE
Save the task definition.

π§± Part 6: Completing the Workflow Diagram
πΉ Step A: Manager Approval Path
Drag Human Task β Create:
- Name: Request Manager Approval
- Task Definition: Manager Approval
- Details PK Item: CLAIM_ID
- Task Outcome Item: TASK_OUTCOME
Connect:
- From Check Amount β False β Human Task

πΉ Step B: Manager Decision Check
Add a Switch after the Human Task:
- Name: Manager Approved?
- Type: Check Workflow Variable
- Variable: TASK_OUTCOME
- Value: APPROVED

πΉ Step C: Process Payment
Both auto-approved and manager-approved paths lead here.
Add Execute Code activity:
- Name: Process Payment
UPDATE expense_claims
SET status = 'PAID'
WHERE claim_id = :CLAIM_ID;Connections:
- Check Amount (True) β Process Payment
- Manager Approved? (True) β Process Payment

πΉ Step D: Rejection Path
Add Send E-Mail activity:
- Name: Send Rejection Notice
- To: &EMPLOYEE_EMAIL.
- Body:
Your expense claim for $&AMOUNT. was rejected.(Optional) Add Execute Code to update status:
UPDATE expense_claims
SET status = 'REJECTED'
WHERE claim_id = :CLAIM_ID;Connect:
- Manager Approved? (False) β Send Rejection Notice

πΉ Step E: End the Workflow
Connect both:
- Process Payment β End
- Send Rejection Notice β End
π Part 7: Creating the Submission Page
Create a Form Page:
- Table: EXPENSE_CLAIMS
- Page Name: Submit Expense
- Items: Name, Email, Amount, Description, Expense Type
βΆ Integrating the Workflow
Go to Processing tab:
Create a Process:
- Type: Workflow
- Action: Start
- Workflow Definition: Expense Reimbursement
Primary Key Item:
- P_CLAIM_ID
Parameter Mapping:
- EMPLOYEE_NAME β P_EMPLOYEE_NAME
- AMOUNT β P_AMOUNT
- CLAIM_ID β P_CLAIM_ID
β οΈ Important: Ensure this process runs after the Automatic Row Processing (DML) process.
π§ͺ Part 8: Testing the Workflow

β Test 1: Auto-Approval
- Submit expense: $40
- Result: Status immediately becomes PAID
π¨βπΌ Test 2: Manager Approval
- Submit expense: $150
- Status remains SUBMITTED
- Approver receives task
- Approve task β Status becomes PAID
π― Final Thoughts
This example demonstrates how powerful and clean Oracle APEX Workflows are for real business processes:
- Conditional routing
- Human approvals
- Automation
- Notifications
You can extend this further with:
- Multi-level approvals
- SLA reminders
- Audit history
- Dynamic approvers
Happy building with Oracle APEX! π
Love coding? Me too! Letβs keep in touch β subscribe to my website for regular chats on Oracle APEX, PL/SQL,SQL JavaScript, and CSS.

