Chuyển tới nội dung chính

VCB — Travel Expense Rules

This document describes how travel expenses are calculated for trips governed by the VCB corporate policy.


Key Concepts​

TermDescription
TripA travel request that groups one or more travellers travelling together (or around the same time). A trip is an organisational container only — expense is always calculated per traveller, never at the trip level.
TravellerAn individual assigned to the trip. Each traveller has their own itinerary — their own departure location, destination(s), and dates. Travellers on the same trip may depart from different cities, arrive at different destinations, and travel on different dates.
LegA single segment of a traveller's itinerary, defined by a departure location, destination, start date, and end date. A traveller's itinerary is an ordered sequence of legs.
Same-day handoffWhen one leg ends on the same calendar day that the next leg begins. This is the only condition under which two of a traveller's legs are linked together.
Connected chainA run of consecutive legs (belonging to one traveller) linked by same-day handoffs. Used only for policy selection — the UI still shows each leg separately.

Important: Travellers on the same trip are calculated completely independently — no factor (distance, accommodation, duration, policy tier) is shared between them. Two travellers going to the same destination on the same dates each get their own separate calculation.

Important: A traveller's legs are sequential in time — they do not overlap in date range. Legs are linked only when they hand off on the same calendar day, never by partial date-range overlap.


Policy Factors​

Two factors select the policy tier (the per-unit rate), evaluated per leg (or per connected chain when legs hand off on the same day). A third value, Duration, does not affect tier selection — it is used only as a multiplier when computing the final amount.

#FactorWhat it measuresUsed for
1DistanceThe travel distance (km) across the leg / connected chain.Tier selection
2AccommodationWhether the leg / chain has a hotel booking or spans more than one calendar day.Tier selection
3DurationThe number of calendar days.Amount multiplier only — not tier selection

Note: The policy tier is chosen from Distance + Accommodation only. Duration does not change which tier applies; it only scales the resulting per-day (or per-km) rate into a total amount.


How Connected Legs Are Handled​

Policy selection is applied per leg. When consecutive legs hand off on the same calendar day (one leg ends on the day the next begins), they are linked into one connected chain, and the tier-selection factors (Distance and Accommodation) are computed across the whole chain.

Legs that do not share a handoff day — including legs that are merely adjacent (one ends the day before the next begins) — are not linked and are evaluated independently.

Important: Linking legs into a chain only affects policy calculation. The UI continues to display each leg separately as originally defined.


Calculation Rules​

1. Distance​

  • Distance per leg is calculated using the Google Distance API (departure → destination).
  • For a connected chain, distance is the sum of each consecutive hop along the chain (leg 1 → leg 2 → leg 3 …).
  • The chain distance is used to select the policy tier.

Example:

LegRouteDates
AHCM → HanoiJun 1 – Jun 3
BHanoi → Da NangJun 3 – Jun 5

Leg A ends Jun 3 and leg B begins Jun 3 → same-day handoff → one connected chain. Chain distance = (HCM → Hanoi) + (Hanoi → Da Nang) → used to select the policy tier.


2. Duration​

  • Duration does not select the policy tier. It is used only as a multiplier applied to the per-day rate (chosen via Distance + Accommodation) to produce the final amount.
  • Duration is the count of calendar days, computed so that a handoff day is counted only once.
  • Within a chain, each leg gives up its handoff day to the next leg: a leg whose end day equals the next leg's begin day contributes endDay − beginDay days; the final leg in the chain contributes its full inclusive day count.

Example:

LegDatesDays contributedWorking
AJun 1 – Jun 32Hands Jun 3 to B → 3 − 1
BJun 3 – Jun 53Final leg → inclusive Jun 3,4,5

Chain duration = 2 + 3 = 5 days (unique days Jun 1–5; Jun 3 counted once).


3. Accommodation​

A leg / connected chain is treated as having accommodation when either of these is true:

  1. Hotel booking — the leg has an active or external hotel booking, or
  2. Multi-day span — the chain spans more than one calendar day (its earliest start and latest end fall on different calendar days), regardless of whether a hotel was booked.

In other words, only a single-calendar-day leg with no hotel booking is treated as not having accommodation. Any chain that crosses into a second calendar day is treated as having accommodation automatically.

Example (hotel booking):

LegDatesHotel Booked?
AJun 5 – Jun 5Yes

Single-day leg, but it has a hotel booking → treated as has accommodation.

Example (multi-day span, no hotel):

LegDatesHotel Booked?
AJun 1 – Jun 4No

The leg spans Jun 1 → Jun 4 (more than one calendar day), so it is treated as has accommodation even though no hotel was booked.

Known limitation: Accommodation is evaluated per leg. For a multi-leg chain the multi-day span condition is applied across the chain, but a hotel booked on one leg is not automatically propagated to a single-day sibling leg in the same chain. See the test cases for the affected edge case.


Summary: Connected Chain Behaviour​

FactorHow it is computed for the connected chain
DistanceSum of each consecutive hop along the chain
DurationCalendar days with handoff days counted once (each leg gives up its handoff day to the next)
Accommodationtrue if a leg has a hotel booking or the chain spans more than one calendar day

Calculation Flow​

Calculation flow
For each traveller:
1. Take the traveller's ordered list of legs.
2. Link consecutive legs into a connected chain when one leg ends on the
same calendar day the next leg begins (same-day handoff).
Legs without a same-day handoff are standalone.
3. For each chain (or standalone leg):
a. Distance → sum each consecutive hop along the chain.
b. Duration → calendar days, counting each handoff day only once.
c. Accommodation → true if a leg has a hotel booking,
OR the chain spans more than one calendar day.
4. Select the policy tier for each chain using: Distance + Accommodation.
5. Compute the amount: per-unit rate (from the selected tier) × Duration
(days for per-day rates, or distance for per-km rates).
6. Display results on the UI per original leg (not per connected chain).

Notes​

  • A traveller may or may not choose to book a flight or hotel for any given leg — both are optional. Accommodation status is true when a hotel booking exists or when the leg / chain spans more than one calendar day.
  • Legs that do not hand off to another leg on the same calendar day are evaluated individually using the same factors.
  • A traveller's legs are sequential and never overlap in date range; legs are linked only by same-day handoffs, not by partial date-range overlap.
  • Linking legs into a chain is a calculation concept only; individual legs remain unchanged in the UI and in stored data.
  • Travellers on the same trip are fully independent. Different departure cities, destinations, and dates between travellers have no effect on each other's calculation.