Skip to main content

SCG — Travel Expense Test Cases

Test cases for verifying the SCG computed values: Time (duration in hours, in UTC), Location (regulated rates), and the expense amount produced by the SCG formula.

Formula reminder: with duration H hours, fullDays = floor(H / 24) is charged at the full-day rate; the leftover remainderHours = H − fullDays·24 is charged 0 if < 5h, the half-day rate if 5–<12h, and the full-day rate if ≥ 12h.

Model reminder: all leg-to-leg comparisons (ordering, same-day handoff) are evaluated in UTC; the UI shows/accepts the local time of the location. A later leg's startTime must be ≥ the previous leg's endTime (UTC). Two legs link into a connected chain only when one ends on the same UTC calendar day the next begins. A chain's duration is the sum of each leg's duration — gaps between legs are not counted.

Unless stated otherwise, the examples use a single location with full-day rate 190,000 and half-day rate 95,000.


Group 1 — Single Leg (Standalone)​

Exercises each branch of the remainder rule. A standalone leg has no same-day handoff.


TC-01 — Remainder below the floor (< 5h)​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 08:00Jun 1, 12:004h

Expected output:

StepValue
H4h
fullDays0
remainderHours4h → < 5h → drop
Amount0

TC-02 — Remainder in the half-day band (5–<12h)​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 08:00Jun 1, 16:008h

Expected output:

StepValue
H8h
fullDays0
remainderHours8h → 5–<12h → half-day
Amount0 + 95,000 = 95,000

TC-03 — Remainder at/above the full-day threshold (≥ 12h)​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 06:00Jun 1, 19:0013h

Expected output:

StepValue
H13h
fullDays0
remainderHours13h → ≥ 12h → full-day
Amount0 + 190,000 = 190,000

TC-04 — Whole day plus a half-day remainder​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 08:00Jun 2, 15:0031h

Expected output:

StepValue
H31h
fullDays1 (24h)
remainderHours7h → 5–<12h → half-day
Amount190,000 + 95,000 = 285,000

TC-05 — Multiple whole days plus a full-day remainder​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 08:00Jun 3, 21:0061h

Expected output:

StepValue
H61h
fullDays2 (48h)
remainderHours13h → ≥ 12h → full-day
Amount2 × 190,000 + 190,000 = 570,000

TC-06 — Exact whole day (zero remainder)​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 08:00Jun 2, 08:0024h

Expected output:

StepValue
H24h
fullDays1
remainderHours0h → < 5h → drop
Amount190,000 + 0 = 190,000

Group 2 — Connected Chains (Same-Day Handoff, UTC)​

Consecutive legs where one leg ends on the same UTC calendar day the next begins. Chain duration = sum of each leg's duration.


TC-07 — Two legs, same UTC day, gap not counted​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 08:00Jun 1, 12:004h
BXJun 1, 15:00Jun 1, 22:007h

Handoff: A ends Jun 1, B begins Jun 1 (same UTC day) → one connected chain.

Expected output (connected chain):

StepValueWorking
H11h4h + 7h (the 12:00→15:00 gap is not counted)
fullDays0
remainderHours11h → 5–<12h → half-day
Amount95,000

TC-08 — Multi-day chain over consecutive handoffs​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 20:00Jun 2, 06:0010h
BXJun 2, 09:00Jun 3, 11:0026h

Handoff: A ends Jun 2, B begins Jun 2 (same UTC day) → connected chain.

Expected output (connected chain):

StepValueWorking
H36h10h + 26h
fullDays1 (24h)
remainderHours12h → ≥ 12h → full-day
Amount190,000 + 190,000 = 380,000

Group 3 — Independent Legs (No Same-Day Handoff)​

Legs that do not share a UTC handoff day are evaluated separately, each with its own formula.


TC-09 — Adjacent UTC days, no shared day → not linked​

A ends Jun 1 (UTC); B begins Jun 2 (UTC) — different UTC days, only 2h apart → not linked.

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 06:00Jun 1, 23:0017h
BXJun 2, 01:00Jun 2, 09:008h

Expected output (two independent legs):

LegHfullDaysRemainderAmount
A17h017h → full-day190,000
B8h08h → half-day95,000

No linking occurs — proximity in clock time does not matter, only a shared UTC calendar day does.


Group 4 — Timezone & Ordering (UTC vs. Local)​

The non-overlap and handoff checks run on UTC; the UI displays local time. These cases show where the two disagree.


TC-10 — Looks fine locally, overlaps in UTC → rejected​

Input (as entered on the UI, local time):

LegLocation (TZ)Local startLocal end→ UTC start→ UTC end
ATokyo (UTC+9)Jun 2, 08:00Jun 2, 08:00Jun 1, 23:00Jun 1, 23:00
BBangkok (UTC+7)Jun 2, 05:00Jun 2, 13:00Jun 1, 22:00Jun 2, 06:00

Expected output: Invalid ordering. In local time B (05:00) appears to precede A's end (08:00) on the same day, but in UTC B.start = Jun 1 22:00 < A.end = Jun 1 23:00 → overlap → the constraint leg[n+1].startTime ≥ leg[n].endTime (UTC) fails. The system rejects the itinerary.


TC-11 — Same-day handoff decided in UTC, not local​

Input:

LegLocation (TZ)Local startLocal end→ UTC start→ UTC end
ABangkok (UTC+7)Jun 2, 05:00Jun 2, 05:00Jun 1, 22:00Jun 1, 22:00
BBangkok (UTC+7)Jun 2, 07:00Jun 2, 15:00Jun 2, 00:00Jun 2, 08:00

Expected output: Not a connected chain. Both legs are on Jun 2 locally, but in UTC A ends Jun 1 and B begins Jun 2 — different UTC calendar days → no same-day handoff. The legs are evaluated independently (A: 0h → 0; B: 8h → half-day → 95,000).

Mirror case: legs on two different local days can still share one UTC day and therefore link. The UTC day is always the deciding factor.


Group 5 — Connected Chain Across Different Locations (pending decision)​

The handling of a chain whose legs carry different location rates is not yet finalised. These cases show the result under Option A (time-attributed per day) — the recommended-but-unconfirmed approach in the rules doc.

Status: proposed. Expected values below assume Option A. They will need revisiting if Option B or C is chosen.

Rates used here: Location X full 190,000 / half 95,000; Location Y full 300,000 / half 150,000.


TC-12 — Whole day in X, remainder day in Y (Option A)​

Input:

LegLocationStart (UTC)End (UTC)Duration
AXJun 1, 08:00Jun 2, 08:0024h
BYJun 2, 10:00Jun 2, 23:0013h

Handoff: A ends Jun 2, B begins Jun 2 → connected chain. Chain H = 24 + 13 = 37h.

Expected output (Option A — per-day attribution):

UnitWindowLocation occupiedRate appliedAmount
Whole day 1first 24h (in A)Xfull-day190,000
Remainder13h → ≥ 12h → full-day (in B)Yfull-day300,000
Total490,000

Under Option B (final destination = Y) the whole 37h would instead bill at Y's rates (300,000 + 300,000 = 600,000). Recorded here to make the open decision concrete.


Group 6 — Multiple Travellers on the Same Trip​

Travellers are calculated completely independently — no time or location factor is shared.


TC-13 — Two travellers, different durations and locations​

Input:

TravellerLegLocationStart (UTC)End (UTC)Duration
AliceAXJun 1, 08:00Jun 2, 15:0031h
BobBXJun 1, 09:00Jun 1, 13:004h

Expected output:

TravellerHfullDaysRemainderAmount
Alice31h17h → half-day285,000
Bob4h04h → drop0

Bob's short leg has no effect on Alice's calculation, and vice versa.


TC-14 — One traveller has a chain, the other a standalone leg​

Input:

TravellerLegLocationStart (UTC)End (UTC)Duration
AliceAXJun 1, 08:00Jun 1, 12:004h
AliceBXJun 1, 15:00Jun 1, 22:007h
BobCXJun 1, 06:00Jun 2, 18:0036h

Alice: A→B same UTC day → connected chain (H = 11h). Bob: standalone (H = 36h).

Expected output:

TravellerChain/LegHfullDaysRemainderAmount
AliceA + B (chain)11h011h → half-day95,000
BobC (standalone)36h112h → full-day380,000

Group 7 — Edge Cases​


TC-15 — Single traveller, no legs​

Input: No legs assigned.

Expected output: No calculation performed. No expense applied.


TC-16 — Ordering violation (overlap in UTC)​

Input:

LegLocationStart (UTC)End (UTC)
AXJun 1, 08:00Jun 1, 14:00
BXJun 1, 12:00Jun 1, 18:00

Expected output: Invalid. B.start = 12:00 < A.end = 14:00 (UTC) → the legs overlap, violating leg[n+1].startTime ≥ leg[n].endTime. The itinerary is rejected; no amount is computed.


Summary Table​

TCTravellersLegsLinked?HRemainder ruleAmount
TC-0111Standalone4hdrop (<5h)0
TC-0211Standalone8hhalf (5–<12h)95,000
TC-0311Standalone13hfull (≥12h)190,000
TC-0411Standalone31hhalf285,000
TC-0511Standalone61hfull570,000
TC-0611Standalone24hdrop (0h)190,000
TC-0712Chain (same UTC day)11hhalf95,000
TC-0812Chain (handoff)36hfull380,000
TC-0912Independent (diff. UTC day)17h / 8hfull / half190,000 / 95,000
TC-1012———Rejected (UTC overlap)
TC-1112Independent (diff. UTC day)0h / 8hdrop / half0 / 95,000
TC-1212Chain, mixed location37hper-day (Option A)490,000 ⚠️ pending
TC-1321 eachIndependent31h / 4hhalf / drop285,000 / 0
TC-1422 / 1Chain / Standalone11h / 36hhalf / full95,000 / 380,000
TC-1510N/AN/AN/AN/A
TC-1612———Rejected (UTC overlap)