VCB Trip Status Workflow
This page documents the VCB-specific trip lifecycle. It is cloned from the standard Trip Status Workflow, but replaces the broad Awaiting Expense status with simplified expense progress statuses.
The key VCB requirement is that once a traveller submits an expense with value greater than 0, the user should see Reimbursement Pending until the expense is either reimbursed or rejected. If an expense is rejected, the user should see Submit Expense again because they need to update details and resubmit.
Expenses with total value equal to 0 are excluded from the VCB expense status calculation.
Overview
The trip workflow starts with company-level routing:
- A trip is created.
- If the company does not use trip proposals, this workflow is not applicable.
- If the company uses trip proposals but does not use expenses, the trip follows the standard flow.
- If the company uses both trip proposals and expenses, the trip follows the VCB expense flow.
Status Definitions
| Status | trips.status enum | Meaning |
|---|---|---|
Pending | 0 (pending) | Trip proposal was submitted and is waiting for approval. |
Approved | 1 (approved) | Trip was approved and the trip end datetime has not passed yet. |
Awaiting Re-declaration | Derived, not stored in trips.status | Trip end has passed and the system is waiting for the employee to re-declare, if re-declaration is enabled. |
Pending Re-declaration | Derived, not stored in trips.status | Re-declaration was submitted and is waiting for approver action. |
Submit Expense | Derived, not stored in trips.status | The viewer has no valid positive-value submitted expense, has a positive-value draft expense, or has a positive-value rejected expense that needs details updated and resubmitted. |
Reimbursement Pending | Derived, not stored in trips.status | The viewer has submitted positive-value expenses that are still waiting for approval, reimbursement submission, or payment. |
Completed | Derived, not stored in trips.status | The trip is finished and no further action is required. For VCB expense trips, this means all relevant positive-value expense items are reimbursed. |
Rejected | 2 (rejected) | The trip proposal or re-declaration was rejected. |
Canceled | 3 (canceled) | The trip was canceled before completion. |
Confirmed | 4 (confirmed) | The trip was confirmed and is ready to continue through the applicable workflow. |
Type Definitions
| Type | trips.type enum | Meaning |
|---|---|---|
Personal | 0 (personal) | Personal trip. |
Business | 1 (business) | Business trip. |
Date-Based Completion Rule
For the standard flow, a trip becomes Completed when:
current_datetime > trip_end_datetime
Status calculation rules:
Pending: waiting for approval.Approved:trip_end_datetimehas not passed.Completed:trip_end_datetimehas passed.Rejected: rejected by the approver.Canceled: canceled before completion.
Use the full datetime value, including time and timezone, when evaluating completion.
VCB Expense Status Logic
The VCB expense flow replaces the broad Awaiting Expense status with these simplified statuses:
Submit Expense -> Reimbursement Pending -> Completed
The previous detailed statuses below are now merged into Reimbursement Pending for VCB:
Pending Approval
Submit for Reimbursement
Reimbursement Pending
This means once the user submits a positive-value expense, the displayed status remains Reimbursement Pending until the expense is reimbursed or rejected.
If the expense is rejected, the displayed status becomes Submit Expense, because the user needs to update the expense details and resubmit.
Expense Value Rule
Only expenses with total value greater than 0 are counted in the VCB expense status calculation.
Expenses with total value equal to 0 must be ignored for this calculation:
- They do not count toward
totalExpenseItem. - They do not count toward
draft,rejected,reviewing,approvedByApprover,approved, orreimbursed. - They cannot make the trip become
Reimbursement PendingorCompleted.
If a viewer only has zero-value expenses, the viewer is treated as having no valid expense items for this status calculation.
Expense Item Status Mapping
| Expense count field | Expense item state | VCB display status |
|---|---|---|
draft | Positive-value expense exists but has not been submitted | Submit Expense |
rejected | Positive-value expense was rejected and needs details updated | Submit Expense |
reviewing | Positive-value expense is waiting for approver review | Reimbursement Pending |
approvedByApprover | Positive-value expense was approved by approver but is not fully reimbursed yet | Reimbursement Pending |
approved | Positive-value expense was submitted for reimbursement and is waiting for payment | Reimbursement Pending |
reimbursed | Positive-value expense has been reimbursed | Completed |
totalExpenseItem | Total positive-value expense items in the calculation scope | Used to determine empty and completed states |
Calculation Rule
Apply this rule in order using only positive-value expense items:
if totalExpenseItem === 0
-> Submit Expense
if draft > 0
-> Submit Expense
if rejected > 0
-> Submit Expense
if reimbursed === totalExpenseItem
-> Completed
if reviewing > 0 || approvedByApprover > 0 || approved > 0
-> Reimbursement Pending
The priority is intentional:
- Zero-value expense items are ignored.
draftandrejectedpositive-value items block completion because the user still needs to submit or update details.reimbursed === totalExpenseItemmeans all relevant positive-value expenses are finished.- Any positive-value submitted but unfinished expense is shown as
Reimbursement Pending.
Reference Implementation
type VcbTripExpenseStatus =
| 'submit_expense'
| 'reimbursement_pending'
| 'completed';
type ExpenseItem = {
status?: string;
totalAmount?: number;
};
type ExpenseStatusCount = {
draft?: number;
rejected?: number;
reviewing?: number;
approvedByApprover?: number;
approved?: number;
reimbursed?: number;
totalExpenseItem?: number;
};
const isPositiveValueExpense = (expense: ExpenseItem): boolean => {
return Number(expense.totalAmount ?? 0) > 0;
};
const getVcbTripExpenseStatusFromCounts = (
item: ExpenseStatusCount,
): VcbTripExpenseStatus => {
const totalExpenseItem = Number(item.totalExpenseItem ?? 0);
const draft = Number(item.draft ?? 0);
const rejected = Number(item.rejected ?? 0);
const reviewing = Number(item.reviewing ?? 0);
const approvedByApprover = Number(item.approvedByApprover ?? 0);
const approved = Number(item.approved ?? 0);
const reimbursed = Number(item.reimbursed ?? 0);
if (totalExpenseItem === 0) {
return 'submit_expense';
}
if (draft > 0) {
return 'submit_expense';
}
if (rejected > 0) {
return 'submit_expense';
}
if (reimbursed === totalExpenseItem) {
return 'completed';
}
if (reviewing > 0 || approvedByApprover > 0 || approved > 0) {
return 'reimbursement_pending';
}
return 'submit_expense';
};
The count input must already exclude zero-value expenses. If the client calculates counts from raw expense items, filter by value first:
const positiveValueExpenses = expenses.filter(isPositiveValueExpense);
Viewer-Specific Rules
Traveller View
Traveller view must calculate expense status using only the current traveller's positive-value expense items.
The purpose is to answer:
What do I need to do next for my own expenses?
Example:
| Current traveller's positive-value expense counts | Traveller sees |
|---|---|
totalExpenseItem = 0 | Submit Expense |
draft > 0 | Submit Expense |
rejected > 0 | Submit Expense |
reviewing > 0 | Reimbursement Pending |
approvedByApprover > 0 | Reimbursement Pending |
approved > 0 | Reimbursement Pending |
reimbursed === totalExpenseItem | Completed |
Trip Owner View
Trip owner view must calculate expense status using all travellers' positive-value expense items in the trip.
The purpose is to answer:
What is the overall reimbursement progress of this trip?
The same rule applies, but the counts are aggregated across every traveller in the trip after excluding zero-value expenses.
Example:
| All travellers' positive-value expense counts | Trip owner sees |
|---|---|
Any traveller has draft > 0 | Submit Expense |
Any traveller has rejected > 0 | Submit Expense |
No draft or rejected, but any traveller has reviewing > 0 | Reimbursement Pending |
No draft or rejected, but any traveller has approvedByApprover > 0 | Reimbursement Pending |
No draft or rejected, but any traveller has approved > 0 | Reimbursement Pending |
| All travellers' positive-value expense items are reimbursed | Completed |
Traveller vs Trip Owner Example
| Traveller | Positive-value expense status counts | Traveller sees |
|---|---|---|
| Traveller A | reimbursed = 2, totalExpenseItem = 2 | Completed |
| Traveller B | reviewing = 1, totalExpenseItem = 1 | Reimbursement Pending |
| Traveller C | rejected = 1, totalExpenseItem = 1 | Submit Expense |
| Traveller D | zero-value expenses only | Submit Expense |
Trip owner aggregated counts after excluding zero-value expenses:
rejected = 1
reviewing = 1
reimbursed = 2
totalExpenseItem = 4
Trip owner sees:
Submit Expense
Reason: at least one traveller has a positive-value rejected expense that requires update and resubmission. Zero-value expenses are ignored.
Flow 1: Standard Trip Flow
This flow applies when trip proposals are enabled and expenses are not used.
Transitions
- Submission creates a trip in
Pending. - If the approver accepts the proposal, the trip moves to
Approved. - While the trip end datetime has not passed, the trip stays
Approved. - After the trip end datetime passes, the trip moves to
Completed. - If the approver rejects the proposal, the trip moves to
Rejected. - If the employee edits and resubmits after rejection, the trip re-enters the approval flow.
Key Point
In the standard flow, there is only one post-approval state before completion:
Pending -> Approved -> Completed
If rejected, the path is:
Pending -> Rejected
Flow 2: VCB Expense Flow With Re-declaration Enabled
This flow applies when the company uses expenses and requires re-declaration after the trip ends.
Transitions
- The trip is first approved and remains
Approvedwhile the trip end datetime has not passed. - Once the trip end datetime passes, the trip moves to
Awaiting Re-declaration. - If the employee does not re-declare, the trip remains in
Awaiting Re-declaration. - If the employee submits a re-declaration, the trip moves to
Pending Re-declaration. - If the approver rejects the re-declaration, the trip moves to
Rejected. - If the approver accepts the re-declaration, the trip enters the VCB expense status flow.
- The trip moves through the simplified VCB expense statuses using only positive-value expenses:
Submit Expense -> Reimbursement Pending -> Completed
If a positive-value expense is rejected during the expense process, the displayed status returns to:
Submit Expense
Journey Summary
Successful path:
Pending -> Approved -> Awaiting Re-declaration -> Pending Re-declaration -> Submit Expense -> Reimbursement Pending -> Completed
Rejected path for trip proposal or re-declaration:
Pending -> Approved -> Awaiting Re-declaration -> Pending Re-declaration -> Rejected
Rejected expense path:
Submit Expense -> Reimbursement Pending -> Submit Expense
Flow 3: VCB Expense Flow With Re-declaration Disabled
This flow applies when the company uses expenses but does not require re-declaration.
Transitions
- The trip is approved and remains
Approvedwhile the trip end datetime has not passed. - After the trip end datetime passes, the trip moves directly into the VCB expense status flow.
- The trip moves through the simplified VCB expense statuses using only positive-value expenses:
Submit Expense -> Reimbursement Pending -> Completed
If a positive-value expense is rejected during the expense process, the displayed status returns to:
Submit Expense
Journey Summary
Pending -> Approved -> Submit Expense -> Reimbursement Pending -> Completed
Rejected expense path:
Submit Expense -> Reimbursement Pending -> Submit Expense
Routing Rules
Use these rules to determine which flow applies:
- If trip proposals are disabled, the trip proposal workflow does not apply.
- If trip proposals are enabled and expenses are disabled, use the standard trip flow.
- If trip proposals are enabled and expenses are enabled for VCB, use the VCB expense flow.
- If expenses are enabled, re-declaration settings determine whether the trip goes through
Awaiting Re-declarationandPending Re-declarationbefore entering the VCB expense status flow.
Implementation Notes
- Do not store the VCB expense statuses directly in
trips.statusunless the data model is intentionally changed. - The VCB expense statuses should be derived from positive-value expense item counts.
- Expenses with total value equal to
0should be ignored for this status calculation. Submit ExpenseandReimbursement Pendingreplace the broadAwaiting Expensedisplay status for VCB expense trips.Pending Approval,Submit for Reimbursement, and the previous detailed payment-pending step are all displayed asReimbursement Pendingfor VCB.- Rejected positive-value expense items should be displayed as
Submit Expense, because the user needs to update details and resubmit. Completedfor VCB expense trips should be derived only when all relevant positive-value expense items in the viewer's calculation scope are reimbursed.- Traveller view must calculate using only the current traveller's positive-value expense items.
- Trip owner view must calculate using all travellers' positive-value expense items in the trip.
- All comparisons against trip end must use the full datetime value rather than only the calendar date.
RejectedandCanceledare terminal trip-level states until the employee submits a new or edited request.