Reject an unsuitable travel-data quote
Prepared with AI assistance for Portproof, which sells travel eSIM plans. Every offer, price, allowance and itinerary below is fictional. The script runs offline and makes no device, carrier, purchase or account request.
A connectivity comparison can produce the wrong answer with perfectly correct multiplication. The cheapest numeric result is irrelevant if it omits the return country, ends before the last required date or has an unknown additional charge.
Separate eligibility from cost. This small Python worksheet first asks whether an offer can meet a defined trip. Only an eligible offer with known extra costs receives a comparable incremental total. Missing cost is a distinct state, rather than zero.
Define the question before the formula
The example compares extra cost for one trip, excluding any already-paid home subscription common to the choices. If a carrier requires another commitment because of the trip, that extra belongs in the input. Taxes, fees or other mandatory extras must be entered as known amounts; leaving other_extra as None produces unknown_cost.
Apple's international eSIM guidance distinguishes included home-plan roaming, travel passes and separately purchased plans. That makes a blanket “eSIM is cheaper” rule unsuitable. The worksheet represents those alternatives without using any current provider's advertised rate.
| Input | Meaning in this teaching model |
|---|---|
visits |
Explicit date/country pairs when data is required |
required_gb |
A measured planning estimate, not a generic per-day allowance |
countries |
The exact fictional country set offered |
first_valid_date, last_valid_date |
Inclusive calendar dates for this example |
included_gb |
A known sufficient allowance to test against the estimate |
fixed_extra |
Additional upfront trip cost |
per_chargeable_day, chargeable_days |
A rate and explicitly identified trigger days |
other_extra |
Known additional cost, or unknown as None |
The date model is intentionally coarse. A real plan can expire at a precise timestamp or start on installation, network attachment or first use. Convert its actual terms into the required access window before comparing; do not use this calendar example to infer a purchased plan's activation rights or expiry time. Country coverage also does not prove signal on a specific road or inside a building.
Keep validation gates visible
The baseline is seven days, two fictional covered destinations and an estimated 6 GB. A EUR 8 charge on each of seven specified days produces EUR 56. A fictional 7 GB travel plan produces EUR 19. An eligible home plan with already-included roaming produces EUR 0 extra. The comparison changes when only two days trigger the pass: EUR 16.
The additional fixtures remove one country, end validity early, reduce allowance and leave an extra cost unknown. None should be silently ranked beside the eligible offers. A separate check refuses comparison across EUR and USD; the script does not invent an exchange rate.
Save the following as worksheet.py and run python3 worksheet.py. It uses Python 3.9 or newer and only the standard library. All monetary inputs use Decimal from strings. The fixture requires non-negative, finite cent amounts; it is a teaching comparison, not a checkout or tax engine.
"""Offline teaching worksheet. Every plan and price below is fictional."""
from dataclasses import dataclass, replace
from datetime import date, timedelta
from decimal import Decimal
import json
import platform
@dataclass(frozen=True)
class Trip:
visits: tuple
required_gb: Decimal
@dataclass(frozen=True)
class Offer:
label: str
currency: str
countries: frozenset
first_valid_date: date
last_valid_date: date
included_gb: Decimal
fixed_extra: Decimal
per_chargeable_day: Decimal
chargeable_days: frozenset
other_extra: object # Decimal when known; None means unknown, never zero.
def evaluate(trip, offer):
required_dates = {day for day, country in trip.visits}
if not trip.visits:
raise ValueError("empty_itinerary")
if not trip.required_gb.is_finite() or trip.required_gb < 0:
raise ValueError("invalid_required_gb")
if not offer.included_gb.is_finite() or offer.included_gb < 0:
raise ValueError("invalid_allowance")
if not offer.chargeable_days.issubset(required_dates):
raise ValueError("chargeable_day_outside_itinerary")
reasons = []
if any(country not in offer.countries for day, country in trip.visits):
reasons.append("coverage")
if any(not offer.first_valid_date <= day <= offer.last_valid_date
for day in required_dates):
reasons.append("validity")
if trip.required_gb > offer.included_gb:
reasons.append("allowance")
if reasons:
return {"label": offer.label, "status": "ineligible", "reasons": reasons}
if offer.other_extra is None:
return {"label": offer.label, "status": "unknown_cost"}
amounts = (offer.fixed_extra, offer.per_chargeable_day, offer.other_extra)
if any(not isinstance(x, Decimal) or not x.is_finite() or x < 0
or x % Decimal("0.01") for x in amounts):
raise ValueError("invalid_cent_amount")
total = (offer.fixed_extra + offer.per_chargeable_day
* len(offer.chargeable_days) + offer.other_extra)
return {"label": offer.label, "status": "eligible",
"currency": offer.currency, "incremental_total": f"{total:.2f}"}
def compare_totals(rows):
eligible = [row for row in rows if row["status"] == "eligible"]
if len({row["currency"] for row in eligible}) > 1:
return "different_currencies_no_comparison"
return "same_currency_totals" if eligible else "no_eligible_total"
def main():
start = date(2026, 11, 1)
visits = tuple((start + timedelta(days=i), "FR" if i < 4 else "ES")
for i in range(7))
trip = Trip(visits, Decimal("6"))
days = frozenset(day for day, country in visits)
travel = Offer("fictional_travel", "EUR", frozenset({"FR", "ES"}),
start, start + timedelta(days=9), Decimal("7"),
Decimal("19.00"), Decimal("0.00"), frozenset(), Decimal("0.00"))
carrier = replace(travel, label="fictional_daily_pass", included_gb=Decimal("10"),
fixed_extra=Decimal("0.00"), per_chargeable_day=Decimal("8.00"),
chargeable_days=days)
included = replace(carrier, label="fictional_included_roaming",
per_chargeable_day=Decimal("0.00"))
checks = []
def check(label, condition):
assert condition, label
checks.append({"case": label, "result": "pass"})
baseline = [evaluate(trip, offer) for offer in (carrier, travel, included)]
for row, expected in zip(baseline, ("56.00", "19.00", "0.00")):
check(row["label"], row["incremental_total"] == expected)
assert compare_totals(baseline) == "same_currency_totals"
failures = [
evaluate(trip, replace(travel, label="missing_country", countries=frozenset({"FR"}))),
evaluate(trip, replace(travel, label="expires_early", last_valid_date=start+timedelta(days=5))),
evaluate(trip, replace(travel, label="too_little_data", included_gb=Decimal("5"))),
evaluate(trip, replace(travel, label="unknown_extra", other_extra=None)),
]
for row, reason in zip(failures[:3], ("coverage", "validity", "allowance")):
check(row["label"], row.get("reasons") == [reason])
check("unknown_extra", failures[3]["status"] == "unknown_cost"
and "incremental_total" not in failures[3])
two_days = evaluate(trip, replace(carrier, chargeable_days=frozenset(sorted(days)[:2])))
check("two_chargeable_days", two_days["incremental_total"] == "16.00")
dollars = evaluate(trip, replace(travel, currency="USD"))
check("mixed_currencies", compare_totals([baseline[0], dollars])
== "different_currencies_no_comparison")
try:
evaluate(trip, replace(travel, fixed_extra=Decimal("NaN")))
except ValueError as error:
check("non_finite_price", str(error) == "invalid_cent_amount")
else:
raise AssertionError("non-finite price accepted")
print(json.dumps({"python": platform.python_version(), "scope": "offline fictional inputs",
"baseline": baseline, "rejected_or_unknown": failures,
"two_chargeable_days": two_days, "checks": checks, "checks_passed": len(checks)}, indent=2))
if __name__ == "__main__":
main()
Read states before totals
The recorded 30 October 2026 run passed ten grouped checks. Its baseline totals were EUR 56.00, EUR 19.00 and EUR 0.00. Missing country, early expiry and insufficient allowance returned ineligible with the relevant reason. An unknown extra produced no total. The remaining checks covered two chargeable days, currency mismatch, non-finite money rejection and the baseline comparison state.
These inputs establish no actual price or cheapest provider. They demonstrate that comparing a valid quotation requires preserving what is unknown. For a real purchase, collect current final prices and all required conditions again rather than retaining this fixture's invented values.
Use Portproof's travel eSIM vs roaming guide for the buyer's checklist, then check the current eSIM catalogue against the actual itinerary. The multi-country guide covers destination selection in more depth. Keep home-number calls and texts separate from travel data; the script cannot determine those carrier charges from an eSIM allowance. Python's Decimal reference documents the arithmetic type used here. References were checked on 30 October 2026.
Comments
Join the discussionNo comments yet. Be the first to comment.