Skip to main content

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:

  1. A trip is created.
  2. If the company does not use trip proposals, this workflow is not applicable.
  3. If the company uses trip proposals but does not use expenses, the trip follows the standard flow.
  4. If the company uses both trip proposals and expenses, the trip follows the VCB expense flow.

Status Definitions​

Statustrips.status enumMeaning
Pending0 (pending)Trip proposal was submitted and is waiting for approval.
Approved1 (approved)Trip was approved and the trip end datetime has not passed yet.
Awaiting Re-declarationDerived, not stored in trips.statusTrip end has passed and the system is waiting for the employee to re-declare, if re-declaration is enabled.
Pending Re-declarationDerived, not stored in trips.statusRe-declaration was submitted and is waiting for approver action.
Submit ExpenseDerived, not stored in trips.statusThe 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 PendingDerived, not stored in trips.statusThe viewer has submitted positive-value expenses that are still waiting for approval, reimbursement submission, or payment.
CompletedDerived, not stored in trips.statusThe trip is finished and no further action is required. For VCB expense trips, this means all relevant positive-value expense items are reimbursed.
Rejected2 (rejected)The trip proposal or re-declaration was rejected.
Canceled3 (canceled)The trip was canceled before completion.
Confirmed4 (confirmed)The trip was confirmed and is ready to continue through the applicable workflow.

Type Definitions​

Typetrips.type enumMeaning
Personal0 (personal)Personal trip.
Business1 (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_datetime has not passed.
  • Completed: trip_end_datetime has 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, or reimbursed.
  • They cannot make the trip become Reimbursement Pending or Completed.

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 fieldExpense item stateVCB display status
draftPositive-value expense exists but has not been submittedSubmit Expense
rejectedPositive-value expense was rejected and needs details updatedSubmit Expense
reviewingPositive-value expense is waiting for approver reviewReimbursement Pending
approvedByApproverPositive-value expense was approved by approver but is not fully reimbursed yetReimbursement Pending
approvedPositive-value expense was submitted for reimbursement and is waiting for paymentReimbursement Pending
reimbursedPositive-value expense has been reimbursedCompleted
totalExpenseItemTotal positive-value expense items in the calculation scopeUsed 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:

  1. Zero-value expense items are ignored.
  2. draft and rejected positive-value items block completion because the user still needs to submit or update details.
  3. reimbursed === totalExpenseItem means all relevant positive-value expenses are finished.
  4. 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 countsTraveller sees
totalExpenseItem = 0Submit Expense
draft > 0Submit Expense
rejected > 0Submit Expense
reviewing > 0Reimbursement Pending
approvedByApprover > 0Reimbursement Pending
approved > 0Reimbursement Pending
reimbursed === totalExpenseItemCompleted

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 countsTrip owner sees
Any traveller has draft > 0Submit Expense
Any traveller has rejected > 0Submit Expense
No draft or rejected, but any traveller has reviewing > 0Reimbursement Pending
No draft or rejected, but any traveller has approvedByApprover > 0Reimbursement Pending
No draft or rejected, but any traveller has approved > 0Reimbursement Pending
All travellers' positive-value expense items are reimbursedCompleted

Traveller vs Trip Owner Example​

TravellerPositive-value expense status countsTraveller sees
Traveller Areimbursed = 2, totalExpenseItem = 2Completed
Traveller Breviewing = 1, totalExpenseItem = 1Reimbursement Pending
Traveller Crejected = 1, totalExpenseItem = 1Submit Expense
Traveller Dzero-value expenses onlySubmit 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​

  1. Submission creates a trip in Pending.
  2. If the approver accepts the proposal, the trip moves to Approved.
  3. While the trip end datetime has not passed, the trip stays Approved.
  4. After the trip end datetime passes, the trip moves to Completed.
  5. If the approver rejects the proposal, the trip moves to Rejected.
  6. 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​

  1. The trip is first approved and remains Approved while the trip end datetime has not passed.
  2. Once the trip end datetime passes, the trip moves to Awaiting Re-declaration.
  3. If the employee does not re-declare, the trip remains in Awaiting Re-declaration.
  4. If the employee submits a re-declaration, the trip moves to Pending Re-declaration.
  5. If the approver rejects the re-declaration, the trip moves to Rejected.
  6. If the approver accepts the re-declaration, the trip enters the VCB expense status flow.
  7. 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​

  1. The trip is approved and remains Approved while the trip end datetime has not passed.
  2. After the trip end datetime passes, the trip moves directly into the VCB expense status flow.
  3. 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-declaration and Pending Re-declaration before entering the VCB expense status flow.

Implementation Notes​

  • Do not store the VCB expense statuses directly in trips.status unless 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 0 should be ignored for this status calculation.
  • Submit Expense and Reimbursement Pending replace the broad Awaiting Expense display status for VCB expense trips.
  • Pending Approval, Submit for Reimbursement, and the previous detailed payment-pending step are all displayed as Reimbursement Pending for VCB.
  • Rejected positive-value expense items should be displayed as Submit Expense, because the user needs to update details and resubmit.
  • Completed for 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.
  • Rejected and Canceled are terminal trip-level states until the employee submits a new or edited request.