Orchestrator refactoring + planned amounts

This commit is contained in:
Stephan D
2026-03-11 20:04:10 +01:00
parent 208b4283d0
commit f578278205
111 changed files with 2485 additions and 1517 deletions

View File

@@ -343,83 +343,235 @@ func TestToPaymentOperation_MapsAmount(t *testing.T) {
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_COMPLETED,
})
if got := op.Amount; got != nil {
t.Fatalf("expected nil amount without executed_money, got=%+v", got)
}
if got := op.ConvertedAmount; got != nil {
t.Fatalf("expected no converted_amount for non-fx operation, got=%+v", got)
if got := op.Money; got != nil {
t.Fatalf("expected nil money payload without step money, got=%+v", got)
}
}
func TestToPaymentOperation_PrefersExecutedMoney(t *testing.T) {
op := toPaymentOperation(&orchestrationv2.StepExecution{
StepRef: "step-4b",
StepCode: "hop.4.card_payout.send",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_COMPLETED,
ExecutedMoney: &moneyv1.Money{Amount: "99.95", Currency: "EUR"},
StepRef: "step-4b",
StepCode: "hop.4.card_payout.send",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_COMPLETED,
Money: &orchestrationv2.StepExecutionMoney{
Planned: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "88.00", Currency: "EUR"},
},
Executed: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "99.95", Currency: "EUR"},
},
},
})
if op.Amount == nil {
t.Fatal("expected amount to be mapped")
if op.Money == nil || op.Money.Executed == nil || op.Money.Executed.Amount == nil {
t.Fatal("expected executed amount to be mapped")
}
if got, want := op.Amount.Amount, "99.95"; got != want {
t.Fatalf("amount.value mismatch: got=%q want=%q", got, want)
if got, want := op.Money.Executed.Amount.Amount, "99.95"; got != want {
t.Fatalf("executed amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.Amount.Currency, "EUR"; got != want {
t.Fatalf("amount.currency mismatch: got=%q want=%q", got, want)
if got, want := op.Money.Executed.Amount.Currency, "EUR"; got != want {
t.Fatalf("executed amount.currency mismatch: got=%q want=%q", got, want)
}
if got := op.ConvertedAmount; got != nil {
t.Fatalf("expected no converted_amount for non-fx operation, got=%+v", got)
if op.Money.Planned == nil || op.Money.Planned.Amount == nil {
t.Fatal("expected planned amount to be exposed")
}
if got, want := op.Money.Planned.Amount.Amount, "88.00"; got != want {
t.Fatalf("planned amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.Money.Planned.Amount.Currency, "EUR"; got != want {
t.Fatalf("planned amount.currency mismatch: got=%q want=%q", got, want)
}
if got := op.Money.Executed.ConvertedAmount; got != nil {
t.Fatalf("expected no executed converted_amount for non-fx operation, got=%+v", got)
}
}
func TestToPaymentOperation_UsesPlannedMoneyBeforeExecution(t *testing.T) {
op := toPaymentOperation(&orchestrationv2.StepExecution{
StepRef: "step-4c",
StepCode: "hop.4.card_payout.send",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_PENDING,
Money: &orchestrationv2.StepExecutionMoney{
Planned: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "77.10", Currency: "USD"},
},
},
})
if op.Money == nil || op.Money.Planned == nil || op.Money.Planned.Amount == nil {
t.Fatal("expected planned amount from structured planned money")
}
if got, want := op.Money.Planned.Amount.Amount, "77.10"; got != want {
t.Fatalf("planned amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.Money.Planned.Amount.Currency, "USD"; got != want {
t.Fatalf("planned amount.currency mismatch: got=%q want=%q", got, want)
}
if got := op.Money.Executed; got != nil {
t.Fatalf("expected no executed snapshot before execution, got=%+v", got)
}
}
func TestToPaymentOperation_UsesStructuredMoneyEnvelope(t *testing.T) {
op := toPaymentOperation(&orchestrationv2.StepExecution{
StepRef: "step-4d",
StepCode: "hop.4.card_payout.send",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_PENDING,
Money: &orchestrationv2.StepExecutionMoney{
Planned: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "66.00", Currency: "USD"},
},
Executed: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "67.00", Currency: "USD"},
},
},
})
if op.Money == nil || op.Money.Executed == nil || op.Money.Executed.Amount == nil {
t.Fatal("expected amount from structured executed money")
}
if got, want := op.Money.Executed.Amount.Amount, "67.00"; got != want {
t.Fatalf("executed amount.value mismatch: got=%q want=%q", got, want)
}
if op.Money.Planned == nil || op.Money.Planned.Amount == nil {
t.Fatal("expected planned amount from structured money")
}
if got, want := op.Money.Planned.Amount.Amount, "66.00"; got != want {
t.Fatalf("planned amount.value mismatch: got=%q want=%q", got, want)
}
}
func TestToPaymentOperation_MapsFxTwoAmounts(t *testing.T) {
op := toPaymentOperation(&orchestrationv2.StepExecution{
StepRef: "step-5",
StepCode: "hop.2.settlement.fx_convert",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_COMPLETED,
ConvertedMoney: &moneyv1.Money{Amount: "100.00", Currency: "EUR"},
StepRef: "step-5",
StepCode: "hop.2.settlement.fx_convert",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_COMPLETED,
Money: &orchestrationv2.StepExecutionMoney{
Executed: &orchestrationv2.StepExecutionMoneySnapshot{
ConvertedAmount: &moneyv1.Money{Amount: "100.00", Currency: "EUR"},
},
},
})
if got := op.Amount; got != nil {
if op.Money == nil || op.Money.Executed == nil {
t.Fatal("expected executed snapshot to be mapped")
}
if got := op.Money.Executed.Amount; got != nil {
t.Fatalf("expected nil base amount without executed_money, got=%+v", got)
}
if op.ConvertedAmount == nil {
if op.Money.Executed.ConvertedAmount == nil {
t.Fatal("expected fx converted amount to be mapped")
}
if got, want := op.ConvertedAmount.Amount, "100.00"; got != want {
if got, want := op.Money.Executed.ConvertedAmount.Amount, "100.00"; got != want {
t.Fatalf("converted amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.ConvertedAmount.Currency, "EUR"; got != want {
if got, want := op.Money.Executed.ConvertedAmount.Currency, "EUR"; got != want {
t.Fatalf("converted amount.currency mismatch: got=%q want=%q", got, want)
}
}
func TestToPaymentOperation_UsesPlannedFxAmountsBeforeExecution(t *testing.T) {
op := toPaymentOperation(&orchestrationv2.StepExecution{
StepRef: "step-5b",
StepCode: "hop.2.settlement.fx_convert",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_PENDING,
Money: &orchestrationv2.StepExecutionMoney{
Planned: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "109.50", Currency: "USDT"},
ConvertedAmount: &moneyv1.Money{Amount: "100.00", Currency: "EUR"},
},
},
})
if op.Money == nil || op.Money.Planned == nil {
t.Fatal("expected planned snapshot from structured money")
}
if got, want := op.Money.Planned.Amount.Amount, "109.50"; got != want {
t.Fatalf("base amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.Money.Planned.Amount.Currency, "USDT"; got != want {
t.Fatalf("base amount.currency mismatch: got=%q want=%q", got, want)
}
if op.Money.Planned.ConvertedAmount == nil {
t.Fatal("expected fx converted amount from structured planned money")
}
if got, want := op.Money.Planned.ConvertedAmount.Amount, "100.00"; got != want {
t.Fatalf("converted amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.Money.Planned.ConvertedAmount.Currency, "EUR"; got != want {
t.Fatalf("converted amount.currency mismatch: got=%q want=%q", got, want)
}
if got := op.Money.Executed; got != nil {
t.Fatalf("expected nil executed snapshot before execution, got=%+v", got)
}
}
func TestToPaymentOperation_UsesStructuredFxMoneyEnvelope(t *testing.T) {
op := toPaymentOperation(&orchestrationv2.StepExecution{
StepRef: "step-5c",
StepCode: "hop.2.settlement.fx_convert",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_COMPLETED,
Money: &orchestrationv2.StepExecutionMoney{
Planned: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "109.50", Currency: "USDT"},
ConvertedAmount: &moneyv1.Money{Amount: "100.00", Currency: "EUR"},
},
Executed: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "110.00", Currency: "USDT"},
ConvertedAmount: &moneyv1.Money{Amount: "101.00", Currency: "EUR"},
},
},
})
if op.Money == nil || op.Money.Executed == nil || op.Money.Planned == nil {
t.Fatal("expected snapshots from structured money")
}
if got, want := op.Money.Executed.Amount.Amount, "110.00"; got != want {
t.Fatalf("amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.Money.Executed.ConvertedAmount.Amount, "101.00"; got != want {
t.Fatalf("converted amount.value mismatch: got=%q want=%q", got, want)
}
if op.Money.Planned.Amount == nil || op.Money.Planned.ConvertedAmount == nil {
t.Fatal("expected planned amounts from structured money")
}
if got, want := op.Money.Planned.Amount.Amount, "109.50"; got != want {
t.Fatalf("planned amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.Money.Planned.ConvertedAmount.Amount, "100.00"; got != want {
t.Fatalf("planned converted amount.value mismatch: got=%q want=%q", got, want)
}
}
func TestToPaymentOperation_FxWithExecutedMoney_StillProvidesTwoAmounts(t *testing.T) {
op := toPaymentOperation(&orchestrationv2.StepExecution{
StepRef: "step-6",
StepCode: "hop.2.settlement.fx_convert",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_COMPLETED,
ExecutedMoney: &moneyv1.Money{Amount: "109.50", Currency: "USDT"},
ConvertedMoney: &moneyv1.Money{Amount: "100.00", Currency: "EUR"},
StepRef: "step-6",
StepCode: "hop.2.settlement.fx_convert",
State: orchestrationv2.StepExecutionState_STEP_EXECUTION_STATE_COMPLETED,
Money: &orchestrationv2.StepExecutionMoney{
Executed: &orchestrationv2.StepExecutionMoneySnapshot{
Amount: &moneyv1.Money{Amount: "109.50", Currency: "USDT"},
ConvertedAmount: &moneyv1.Money{Amount: "100.00", Currency: "EUR"},
},
},
})
if op.Amount == nil {
if op.Money == nil || op.Money.Executed == nil || op.Money.Executed.Amount == nil {
t.Fatal("expected fx base amount to be mapped")
}
if got, want := op.Amount.Amount, "109.50"; got != want {
if got, want := op.Money.Executed.Amount.Amount, "109.50"; got != want {
t.Fatalf("base amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.Amount.Currency, "USDT"; got != want {
if got, want := op.Money.Executed.Amount.Currency, "USDT"; got != want {
t.Fatalf("base amount.currency mismatch: got=%q want=%q", got, want)
}
if op.ConvertedAmount == nil {
if op.Money.Executed.ConvertedAmount == nil {
t.Fatal("expected fx quote amount to be mapped")
}
if got, want := op.ConvertedAmount.Amount, "100.00"; got != want {
if got, want := op.Money.Executed.ConvertedAmount.Amount, "100.00"; got != want {
t.Fatalf("converted amount.value mismatch: got=%q want=%q", got, want)
}
if got, want := op.ConvertedAmount.Currency, "EUR"; got != want {
if got, want := op.Money.Executed.ConvertedAmount.Currency, "EUR"; got != want {
t.Fatalf("converted amount.currency mismatch: got=%q want=%q", got, want)
}
}