Class CurrencyReconciler
TcoEngine, SavingsCalculatorEngine, MetroOptimizerEngine,
DeploymentWizardEngine, and plan value realization).
Rule: monetary amounts may only be added, subtracted, or compared
when they share a currency. This SDK models prices with no FX rate at all — live
Fabric pricing for an EMEA metro can quote EUR while the bundled cloud-egress reference
figures are USD — so summing across currencies would fabricate a figure that is
simply wrong. When components disagree, this helper refuses to produce a combined total
and instead exposes the per-currency subtotals and a human-readable reason, so the caller
can mark the total unpriced/mixed (mirroring the existing priced/complete
guards) rather than emit a false number labelled as authoritative.
Used two ways:
- as an accumulator (
add(Currency, BigDecimal, BigDecimal)) for a stream of priced components that are meant to sum into one deployment total — it tallies per-currency subtotals and yields a combined total only viamonthlyTotal()/setupTotal(), which are empty when more than one currency is present; - via the static
knownDifferent(String, String)/sameKnownCurrency(String, String)predicates at the two-sided subtract/compare sites (egress − interconnect, baseline − recommended, break-even, payback).
The predicates deliberately treat an unknown (null/blank) currency as
"not provably different": they block a combination only when two currencies are both known
and genuinely differ, so a malformed null currency never silently flips an all-one-currency
calculation to unpriced. Absence is tracked separately via sawUnknownCurrency().
Not thread-safe; each computation builds its own instance.
-
Method Summary
Modifier and TypeMethodDescriptionadd(String currencyCode, BigDecimal monthlyAmount, BigDecimal setupAmount) Records a priced component by currency code.add(Currency currency, BigDecimal monthlyAmount, BigDecimal setupAmount) Records a priced component.addMonthly(Currency currency, BigDecimal monthlyAmount) Records a monthly-only component (setup treated as zero).static CurrencyReconcilercreate()Creates an empty reconciler.The distinct currency codes recorded, in first-seen order.The currencies joined for a message, e.g.The per-currency monthly subtotals for a message, e.g.intHow many distinct currencies were recorded.booleanisEmpty()truewhen no priceable component has been recorded.booleanisMixed()truewhen components span more than one currency, so no single total is valid.booleantruewhen all recorded components share a currency (or none were recorded).static booleanknownDifferent(String a, String b) trueonly when both currencies are known and genuinely differ — the guard for "may I subtract/compare these two?".static booleanknownDifferent(Currency a, Currency b) knownDifferent(String, String)overCurrencyvalues.Monthly subtotal per currency, in first-seen order.The combined monthly total — present only when the components reconcile to a single currency, empty when they aremixed(a cross-currency sum would be false).static booleansameKnownCurrency(String a, String b) truewhen both currencies are known and equal.booleantruewhen at least one component had a null/blank (unreconcilable) currency.Setup subtotal per currency, in first-seen order.The combined setup total, with the same single-currency guard — and the same empty-reconciler caveat — asmonthlyTotal().The sole currency when exactly one was recorded, otherwisenull.soleCurrencyOr(String fallback) The sole currency, orfallbackwhen empty or mixed.
-
Method Details
-
create
Creates an empty reconciler. -
add
Records a priced component. A null/blank currency contributes no amount (it cannot be reconciled) and is remembered viasawUnknownCurrency(); null amounts count as zero.- Parameters:
currency- the component's currency (may be null)monthlyAmount- the component's monthly-recurring amountsetupAmount- the component's one-time setup amount- Returns:
- this reconciler
-
add
public CurrencyReconciler add(String currencyCode, BigDecimal monthlyAmount, BigDecimal setupAmount) Records a priced component by currency code. Seeadd(Currency, BigDecimal, BigDecimal). -
addMonthly
Records a monthly-only component (setup treated as zero). -
isEmpty
public boolean isEmpty()truewhen no priceable component has been recorded. -
sawUnknownCurrency
public boolean sawUnknownCurrency()truewhen at least one component had a null/blank (unreconcilable) currency. -
currencies
-
distinctCurrencyCount
public int distinctCurrencyCount()How many distinct currencies were recorded. -
isMixed
public boolean isMixed()truewhen components span more than one currency, so no single total is valid. -
isReconciled
public boolean isReconciled()truewhen all recorded components share a currency (or none were recorded). -
soleCurrency
The sole currency when exactly one was recorded, otherwisenull. -
soleCurrencyOr
-
monthlyTotal
The combined monthly total — present only when the components reconcile to a single currency, empty when they aremixed(a cross-currency sum would be false).Empty-reconciler caveat: when nothing priceable was recorded — including when every added component carried a null/blank currency — this returns
Optional.of(ZERO), notOptional.empty(): zero is the correct sum of no components, but it is not evidence that anything was priced. Callers must therefore pair this withisEmpty()/sawUnknownCurrency()(as the engines'priced/completeflags do) before presenting the total, or an all-unpriceable accumulation reads as "costs $0" — exactly the fabricated figure this class exists to prevent. -
setupTotal
The combined setup total, with the same single-currency guard — and the same empty-reconciler caveat — asmonthlyTotal(). -
monthlySubtotals
Monthly subtotal per currency, in first-seen order. -
setupSubtotals
Setup subtotal per currency, in first-seen order. -
describeCurrencies
The currencies joined for a message, e.g."USD and EUR". -
describeMonthlySubtotals
The per-currency monthly subtotals for a message, e.g."USD 2000.00, EUR 350.00". -
knownDifferent
-
knownDifferent
knownDifferent(String, String)overCurrencyvalues. -
sameKnownCurrency
-