Multi-currency: pro-rata future application and legacy failures - #58
Open
ItsThompson wants to merge 6 commits into
Open
Multi-currency: pro-rata future application and legacy failures#58ItsThompson wants to merge 6 commits into
ItsThompson wants to merge 6 commits into
Conversation
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
2 times, most recently
from
August 15, 2026 22:55
0f70f3c to
5ee4f2f
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 15, 2026 23:10
5ee4f2f to
32bdfdb
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 15, 2026 23:22
32bdfdb to
5ee38f9
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
2 times, most recently
from
August 15, 2026 23:53
c4c5c39 to
7d1d9a4
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 16, 2026 14:53
7d1d9a4 to
572a432
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 16, 2026 15:17
572a432 to
0748ac4
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
3 times, most recently
from
August 18, 2026 23:36
a065b29 to
8917be9
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
2 times, most recently
from
August 18, 2026 23:51
37f48f5 to
4e5d83f
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 19, 2026 06:30
4e5d83f to
b61f42c
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 19, 2026 19:05
b61f42c to
570136e
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 20, 2026 13:48
570136e to
ed0f649
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 20, 2026 14:58
ed0f649 to
3eee5d9
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 20, 2026 15:10
3eee5d9 to
6c05e3c
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
2 times, most recently
from
August 20, 2026 17:59
956cbc6 to
a813648
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 23, 2026 19:51
a813648 to
ac432f7
Compare
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 23, 2026 20:38
ac432f7 to
6deadfb
Compare
…ror codes Add the MarkProRataFailed query (status -> 'failed' with a typed failure_reason) so the pro-rata application flow can move deterministic schedule failures to failed without a ledger write. Add the SNAPSHOT_CURRENCY_MISSING and MISSING_CAPTURED_RATE_SNAPSHOT finance error codes that classify captured-snapshot and legacy schedule failures.
…snapshot Add a legacy_migration flag to the CreateProRataInstallment contract so Finance can apply legacy pending schedules whose target period reporting currency equals the stored schedule currency. Expense writes a migration snapshot (exchangeRate = "1", exchangeRateSource = "migration") without calling FX, and re-validates the currency match so a caller error never invents a conversion. Regenerate the expense proto.
…d snapshot Rewrite applyPendingProRata to resolve the target reporting currency from the just-created Finance period, pass trusted period context plus the captured snapshot to Expense (no reentrant Finance call, no live provider rate), and mark each schedule applied only after the ledger write succeeds. Deterministic failures (missing snapshot currency, legacy differing currency) move the row to failed with a typed reason; transient Expense write/conversion failures leave the row pending so it can be retried, with no partial expense row visible. Each schedule is applied independently so one failure does not block the rest.
…ailures Add finance service tests for captured-snapshot same/different target currency, missing snapshot currency, expense write failure, legacy same-currency migration application, legacy different-currency failure, and the no-target-period-remains-pending invariant, plus a dashboard excludes-pending-and-failed assertion. Add expense service tests for the legacy migration write, currency-mismatch rejection, different-target snapshot conversion, missing-target-currency rejection, and expense write failure. Update existing CreatePeriodWithProRata tests to the new CreateProRataInstallment contract and wire the MarkProRataFailed mock.
…stic Expense-side defense-in-depth can surface a snapshot_currency_missing failure that Finance's target-only pre-check does not cover (e.g. the transaction currency is missing from the captured snapshot). Previously any Expense error left the schedule pending, stranding it for a retry that would fail identically. classifyProRataExpenseError now inspects the returned error (in-process *apierr.Error or wrapped gRPC codes.FailedPrecondition) and moves the row to failed with snapshot_currency_missing when the failure is deterministic; transient errors still leave the row pending. Also add a failed count to the apply summary log for at-a-glance operator correlation. Addresses review-14 should-fix S1.
- Use int64Ptr for the now-pointer BudgetAmount in the pro-rata test helper - Read the migration drift-guard catalog from the shared currency package instead of the deleted catalog.json
ItsThompson
force-pushed
the
mc/06-prorata-future-application
branch
from
August 24, 2026 06:59
6deadfb to
e22a057
Compare
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
Reworked the Finance pro-rata future-application flow so pending installments are applied only after their target budget period exists. Reporting amounts derive from the captured schedule snapshot. No live provider rates are called. Legacy schedules without captured snapshots are handled without invented rates. Deterministic failures move a schedule to
failedwith a typed reason. Transient failures leave the schedulependingfor retry. Finance marks a rowappliedonly after the Expense ledger write succeeds.What changed
Backend: Finance service
applyPendingProRatato accept the target period, resolve reporting currency locally, and pass trusted period context plus captured snapshot to Expense. Each schedule is applied independently so one failure does not block the rest.applyOneProRataSchedule(captured-snapshot path) andapplyLegacyProRataSchedule(legacy migration path).MarkProRataFailedrepository method and SQL query to move schedules tofailedwith a typedfailure_reason.classifyProRataExpenseErrorto distinguish deterministic failures (snapshot_currency_missing) from transient errors.ErrSnapshotCurrencyMissingandErrMissingCapturedRateSnapshoterror codes.LegacyMigrationflag toCreateProRataInstallmentInputand forwarded it over gRPC.CreatePeriodWithProRatato pass the created period object toapplyPendingProRata.CreatePeriodWithProRatatests to the newCreateProRataInstallmentcontract.Backend: Expense service
legacy_migrationfield toCreateProRataInstallmentRequestproto and regenerated bindings.CreateProRataInstallment: writes a migration snapshot (exchangeRate = "1",exchangeRateSource = "migration") without calling FX.LegacyMigrationflag from gRPC handler to service layer.Tests
Finance service (
GOWORK=off go test ./... -count=1): all packages pass. New test coverage:snapshot_currency_missingfailure classified as deterministic.classifyProRataExpenseErrortable test covering in-process and gRPC error paths.Expense service (
GOWORK=off go test ./... -count=1): all packages pass. Legacy migration and defense-in-depth validation tests added.go vetclean for both services. Workspace build clean.Notes
MarkProRataFailedSQL query is hand-added to the sqlc-generatedfinance.sql.go(sqlc is not installed). It mirrors the existingMarkProRataAppliedpattern. A futuresqlc generaterun will regenerate it identically.pendingby a transient failure. Application is only triggered during period creation. A manual retry endpoint is out of scope for this ticket.References
/Users/thompsontong/Desktop/multi-currency-support-Spec/changesets/changeset-14.md