feat(compute): add precision option to preserve sub-cent integer amounts#281
Open
anttiviljami wants to merge 1 commit into
Open
feat(compute): add precision option to preserve sub-cent integer amounts#281anttiviljami wants to merge 1 commit into
precision option to preserve sub-cent integer amounts#281anttiviljami wants to merge 1 commit into
Conversation
Per-unit rates such as `0.1524 EUR/kWh` and sub-cent rates like
`0.00352 EUR/kWh` are configured by tariff operators with full decimal
precision but the engine's `amount_total` / `unit_amount` integer fields
are rounded to whole cents, which downstream consumers display as
`15 cents` / `€0` / `1 cent` even when the contracted rate is something
else. Today consumers can read the `*_decimal` string fields to recover
precision but every consumer has to remember to do so.
Add an opt-in `precision` option to `computeAggregatedAndPriceTotals`,
defaulting to `DEFAULT_INTEGER_AMOUNT_PRECISION` (2). Callers that need
to render or compute on sub-cent rates can pass
`{ precision: 12 }` (i.e. `DECIMAL_PRECISION`) and receive integer
fields at the same precision the dinero math is done at, with the
`*_decimal` strings unchanged.
The option is threaded through the three internal `convert*Precision`
calls. Default behaviour for every existing caller is identical — all
634 existing tests pass without modification — and three new tests
cover the opt-in path against `0.1524 EUR/kWh` and `0.00352 EUR/kWh`.
Refs https://e-pilot.atlassian.net/browse/STABLE360-11491
Co-authored-by: Claude <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 852d568 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add an opt-in
precisionoption tocomputeAggregatedAndPriceTotalsso consumers can preserve sub-cent precision in the integer amount fields (amount_total,unit_amount,unit_amount_gross, etc.).Why
Per-unit tariff rates are routinely configured at sub-cent precision — e.g.
0.1524 EUR/kWhfor anArbeitspreis Energieline, or0.00352 EUR/kWhfor a small grid-loss surcharge. Today the engine rounds the integer fields to whole cents on the way out (amount_total: 15,amount_total: 0), so any consumer that doesn't fall back to the*_decimalstring fields renders the rates as15 cents/€0/1 cent, in conflict with the contracted tariff sheet and visibly inconsistent with the per-unit detail line displayed beside them. A team-reported reproducer is in STABLE360-11491.The
*_decimalstring fields are already preserved at full precision today and consumers can recover precision through them, but every consumer has to remember to opt in viashouldShowDecimals-style heuristics. Exposing precision as a first-class option closes the loop: callers that need full precision (variable per-unit price displays, ECP charts, customer-facing tariff breakdowns) just request it on the compute call and receive consistent integer + decimal data.What changes
precision?: numberonComputeAggregatedAndPriceTotalsOptions. DefaultDEFAULT_INTEGER_AMOUNT_PRECISION(2).convert*Precisioncalls (convertPriceComponentsPrecision,convertPriceItemPrecision,convertPricingPrecision) atcompute-totals.ts:90/126/145.precision: 12preserves0.1524 EURas152_400_000_000integer cents, (c) sub-cent amounts (0.00352) no longer collapse to0.Backwards compatibility
No behavioural change for any existing caller. All 634 existing tests pass without modification. The
*_decimalstring fields continue to be populated at full precision regardless of the new option, so a consumer that was already reading them sees no diff.Risk
152_400_000_000). Consumers that explicitly opt in must be able to handle these;Number.MAX_SAFE_INTEGERis9_007_199_254_740_992, so a single line item up to ~€90M still fits comfortably and aggregate totals on consumer carts shouldn't approach that ceiling. Documented in the JSDoc.Test plan
pnpm test— 634 + 3 new = 637 tests passing locallytsc --noEmit— cleanpnpm lint— no new warnings introduced (existing warnings on non-null assertions are pre-existing)pnpm build— cleanCloses STABLE360-11491 on the engine side. The journey-monorepo can plug in via
getPricingDetailsFormattedlater (separate MR).🤖 Generated with Claude Opus 4.7