πŸ’Ό Building an Employee Expense Reimbursement Workflow in Oracle APEX

πŸ’Ό Building an Employee Expense Reimbursement Workflow in Oracle APEX

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:

LabelStatic IDData TypePurpose
Employee NameEMPLOYEE_NAMEVARCHAR2Display & routing
Employee EmailEMPLOYEE_EMAILVARCHAR2Notifications
AmountAMOUNTNUMBERApproval logic
Claim IDCLAIM_IDNUMBERDB row reference

2️⃣ Workflow Variables (Internal Logic)

Create these variables:

NameStatic IDData TypePurpose
Task OutcomeTASK_OUTCOMEVARCHAR2APPROVED / REJECTED
ApproverAPPROVERVARCHAR2Who approved

πŸ”€ Part 4: Auto-Approval Logic (Switch Activity)

We’ll automatically approve low-value expenses.

Steps:

  1. Drag a Switch activity after Start
  2. Name it: Check Amount
  3. Type: PL/SQL Expression
  4. Expression:
:AMOUNT < 100

Branches:

  • 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.

Comments

No comments yet. Why don’t you start the discussion?

    Leave a Reply

    Your email address will not be published. Required fields are marked *