Repository navigation
0.11.0 - 2026-09-06
PR #31, PR #32, plus the post-merge review of #32. Full findings in
dev_docs/pull_requests/2026/31-set-default-currency-repromote/CLAUDE_REVIEW.md
and dev_docs/pull_requests/2026/32-currency-e1-display-currency-cache/CLAUDE_REVIEW.md.
Added
- Request-scoped display currency.
Currency.put_request_currency/1/
get_request_currency/0let a host set, per request, the currency a
shopper should see and be charged in, independent of the shop's base
currency.get_base_currency/0(cached),get_display_currency/0and
resolve_display_currency/1resolve it with a fail-safe: an unknown,
disabled, or non-positive-rate code falls back to the base currency and
logs once per process per offending code, rather than crashing or showing
a broken price. Currency.present/3— the one place a base-currency amount becomes a
display-currency amount. Resolves the base and target fresh on every call
(a rate edit is visible on the next call), or, withopts[:rate], uses a
caller's own frozen rate (a cart's or order's snapshot) without
re-checking the target's live usability — a frozen rate must survive the
target being disabled after the freeze.Currency.effective_rate/2— thebase -> targetmultiplier a cart
freezes at creation, rounded to six decimal places.- Currency-table caching (§13).
get_base_currency/0and
get_currency_by_code/1are backed by aPhoenixKit.Cacheinstance
(5 minute TTL), invalidated wholesale by every currency writer. Cuts
Currency.present/3's per-call query cost from 3 to ~0 once warm — a
catalog page converting dozens of prices no longer pays for it per price. - Migration chain V3 — adds
phoenix_kit_orders.base_currency,
.exchange_rateand.base_total(nullable, no backfill), the columns
PhoenixKitBilling.Ordernow declares for a later stage's frozen order
pricing. Added post-merge: PR #32 shipped the schema fields on the
assumption that a core release would add these columns, but the core
release in question had not been published, so everyOrderquery broke
on the currently published core. This chain now adds them itself, using
the same names/types that core release will use, so its own
ADD COLUMN IF NOT EXISTSand backfill still work unchanged once it ships.
Changed
billing_default_currencyis no longer read. Every internal reader
(order/subscription creation, dashboard stats, the order form) now uses
theis_defaultrow ofphoenix_kit_currenciesviaget_base_currency/0.
The dead "Default Currency" select on the settings page (it wrote a
setting nothing read) is removed along with it.
Fixed
set_default_currency/1: re-promoting the currency that is already
default no longer clearsis_defaultentirely. The base-rate
renormalization added in 0.10.0 demoted the target's own row in the
database while the caller's in-memory struct still readis_default: true, so Ecto's changeset diff saw no change and never re-promoted it.
The function now reloads the row before both the guard check and the
promoting changeset, and forces:is_default/:exchange_rateinto the
changeset regardless of what the reload reports.