complete MECE request
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
|
||||
accountingv1 "github.com/tech/sendico/pkg/proto/common/accounting/v1"
|
||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||
paymentv1 "github.com/tech/sendico/pkg/proto/common/payment/v1"
|
||||
quotationv2 "github.com/tech/sendico/pkg/proto/payments/quotation/v2"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
@@ -167,6 +168,68 @@ func TestBuildPlan_RequiresFXUsesSettlementCurrencyForDestinationStep(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPlan_ResolvesIndependentEconomicsKnobs(t *testing.T) {
|
||||
svc := New(nil)
|
||||
orgID := bson.NewObjectID()
|
||||
intent := sampleCardQuoteIntent()
|
||||
intent.SettlementMode = transfer_intent_hydrator.QuoteSettlementModeFixReceived
|
||||
intent.FeeTreatment = transfer_intent_hydrator.QuoteFeeTreatmentDeductFromDestination
|
||||
|
||||
planModel, err := svc.BuildPlan(context.Background(), ComputeInput{
|
||||
OrganizationRef: orgID.Hex(),
|
||||
OrganizationID: orgID,
|
||||
BaseIdempotencyKey: "idem-key",
|
||||
Intents: []*transfer_intent_hydrator.QuoteIntent{intent},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if planModel == nil || len(planModel.Items) != 1 {
|
||||
t.Fatalf("expected single plan item")
|
||||
}
|
||||
item := planModel.Items[0]
|
||||
if item == nil {
|
||||
t.Fatalf("expected plan item")
|
||||
}
|
||||
if got, want := item.ResolvedSettlementMode, paymentv1.SettlementMode_SETTLEMENT_FIX_RECEIVED; got != want {
|
||||
t.Fatalf("unexpected resolved settlement mode: got=%s want=%s", got.String(), want.String())
|
||||
}
|
||||
if got, want := item.ResolvedFeeTreatment, quotationv2.FeeTreatment_FEE_TREATMENT_DEDUCT_FROM_DESTINATION; got != want {
|
||||
t.Fatalf("unexpected resolved fee treatment: got=%s want=%s", got.String(), want.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPlan_DefaultsResolvedFeeTreatmentWhenUnspecified(t *testing.T) {
|
||||
svc := New(nil)
|
||||
orgID := bson.NewObjectID()
|
||||
intent := sampleCardQuoteIntent()
|
||||
intent.SettlementMode = transfer_intent_hydrator.QuoteSettlementModeFixReceived
|
||||
intent.FeeTreatment = transfer_intent_hydrator.QuoteFeeTreatmentUnspecified
|
||||
|
||||
planModel, err := svc.BuildPlan(context.Background(), ComputeInput{
|
||||
OrganizationRef: orgID.Hex(),
|
||||
OrganizationID: orgID,
|
||||
BaseIdempotencyKey: "idem-key",
|
||||
Intents: []*transfer_intent_hydrator.QuoteIntent{intent},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if planModel == nil || len(planModel.Items) != 1 {
|
||||
t.Fatalf("expected single plan item")
|
||||
}
|
||||
item := planModel.Items[0]
|
||||
if item == nil {
|
||||
t.Fatalf("expected plan item")
|
||||
}
|
||||
if got, want := item.ResolvedSettlementMode, paymentv1.SettlementMode_SETTLEMENT_FIX_RECEIVED; got != want {
|
||||
t.Fatalf("unexpected resolved settlement mode: got=%s want=%s", got.String(), want.String())
|
||||
}
|
||||
if got, want := item.ResolvedFeeTreatment, quotationv2.FeeTreatment_FEE_TREATMENT_ADD_TO_SOURCE; got != want {
|
||||
t.Fatalf("unexpected default resolved fee treatment: got=%s want=%s", got.String(), want.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPlan_SelectsGatewaysAndIgnoresIrrelevant(t *testing.T) {
|
||||
svc := New(nil, WithGatewayRegistry(staticGatewayRegistry{
|
||||
items: []*model.GatewayInstanceDescriptor{
|
||||
@@ -405,6 +468,49 @@ func TestCompute_EnrichesRouteConditionsAndTotalCost(t *testing.T) {
|
||||
if got := core.lastQuoteIn.ExecutionConditions.GetPrefundingRequired(); !got {
|
||||
t.Fatalf("expected prefunding_required in build quote input for reserve mode")
|
||||
}
|
||||
if got, want := result.Quote.ResolvedSettlementMode, paymentv1.SettlementMode_SETTLEMENT_FIX_SOURCE; got != want {
|
||||
t.Fatalf("unexpected resolved settlement mode: got=%s want=%s", got.String(), want.String())
|
||||
}
|
||||
if got, want := result.Quote.ResolvedFeeTreatment, quotationv2.FeeTreatment_FEE_TREATMENT_ADD_TO_SOURCE; got != want {
|
||||
t.Fatalf("unexpected resolved fee treatment: got=%s want=%s", got.String(), want.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompute_PropagatesIndependentResolvedEconomics(t *testing.T) {
|
||||
core := &fakeCore{
|
||||
quote: &ComputedQuote{
|
||||
DebitAmount: &moneyv1.Money{Amount: "100", Currency: "USD"},
|
||||
},
|
||||
expiresAt: time.Unix(1000, 0),
|
||||
}
|
||||
svc := New(core)
|
||||
|
||||
orgID := bson.NewObjectID()
|
||||
intent := sampleCardQuoteIntent()
|
||||
intent.SettlementMode = transfer_intent_hydrator.QuoteSettlementModeFixReceived
|
||||
intent.FeeTreatment = transfer_intent_hydrator.QuoteFeeTreatmentDeductFromDestination
|
||||
|
||||
output, err := svc.Compute(context.Background(), ComputeInput{
|
||||
OrganizationRef: orgID.Hex(),
|
||||
OrganizationID: orgID,
|
||||
PreviewOnly: true,
|
||||
Intents: []*transfer_intent_hydrator.QuoteIntent{intent},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if output == nil || len(output.Results) != 1 {
|
||||
t.Fatalf("expected single result")
|
||||
}
|
||||
if output.Results[0].Quote == nil {
|
||||
t.Fatalf("expected quote")
|
||||
}
|
||||
if got, want := output.Results[0].Quote.ResolvedSettlementMode, paymentv1.SettlementMode_SETTLEMENT_FIX_RECEIVED; got != want {
|
||||
t.Fatalf("unexpected resolved settlement mode: got=%s want=%s", got.String(), want.String())
|
||||
}
|
||||
if got, want := output.Results[0].Quote.ResolvedFeeTreatment, quotationv2.FeeTreatment_FEE_TREATMENT_DEDUCT_FROM_DESTINATION; got != want {
|
||||
t.Fatalf("unexpected resolved fee treatment: got=%s want=%s", got.String(), want.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompute_PreviewMarksIndicativeReadiness(t *testing.T) {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package quote_computation_service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||
paymentv1 "github.com/tech/sendico/pkg/proto/common/payment/v1"
|
||||
quotationv2 "github.com/tech/sendico/pkg/proto/payments/quotation/v2"
|
||||
)
|
||||
|
||||
func TestEnsureComputedQuote_UsesItemResolvedEconomicsWhenQuoteUnset(t *testing.T) {
|
||||
src := &ComputedQuote{
|
||||
DebitAmount: &moneyv1.Money{Amount: "10", Currency: "USD"},
|
||||
}
|
||||
item := &QuoteComputationPlanItem{
|
||||
ResolvedSettlementMode: paymentv1.SettlementMode_SETTLEMENT_FIX_RECEIVED,
|
||||
ResolvedFeeTreatment: quotationv2.FeeTreatment_FEE_TREATMENT_DEDUCT_FROM_DESTINATION,
|
||||
}
|
||||
|
||||
got := ensureComputedQuote(src, item)
|
||||
if got == nil {
|
||||
t.Fatalf("expected quote")
|
||||
}
|
||||
if got.ResolvedSettlementMode != paymentv1.SettlementMode_SETTLEMENT_FIX_RECEIVED {
|
||||
t.Fatalf("unexpected resolved settlement mode: %s", got.ResolvedSettlementMode.String())
|
||||
}
|
||||
if got.ResolvedFeeTreatment != quotationv2.FeeTreatment_FEE_TREATMENT_DEDUCT_FROM_DESTINATION {
|
||||
t.Fatalf("unexpected resolved fee treatment: %s", got.ResolvedFeeTreatment.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureComputedQuote_PreservesQuoteResolvedEconomics(t *testing.T) {
|
||||
src := &ComputedQuote{
|
||||
DebitAmount: &moneyv1.Money{Amount: "10", Currency: "USD"},
|
||||
ResolvedSettlementMode: paymentv1.SettlementMode_SETTLEMENT_FIX_SOURCE,
|
||||
ResolvedFeeTreatment: quotationv2.FeeTreatment_FEE_TREATMENT_ADD_TO_SOURCE,
|
||||
}
|
||||
item := &QuoteComputationPlanItem{
|
||||
ResolvedSettlementMode: paymentv1.SettlementMode_SETTLEMENT_FIX_RECEIVED,
|
||||
ResolvedFeeTreatment: quotationv2.FeeTreatment_FEE_TREATMENT_DEDUCT_FROM_DESTINATION,
|
||||
}
|
||||
|
||||
got := ensureComputedQuote(src, item)
|
||||
if got == nil {
|
||||
t.Fatalf("expected quote")
|
||||
}
|
||||
if got.ResolvedSettlementMode != paymentv1.SettlementMode_SETTLEMENT_FIX_SOURCE {
|
||||
t.Fatalf("unexpected resolved settlement mode: %s", got.ResolvedSettlementMode.String())
|
||||
}
|
||||
if got.ResolvedFeeTreatment != quotationv2.FeeTreatment_FEE_TREATMENT_ADD_TO_SOURCE {
|
||||
t.Fatalf("unexpected resolved fee treatment: %s", got.ResolvedFeeTreatment.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureComputedQuote_DefaultsResolvedEconomicsWhenUnset(t *testing.T) {
|
||||
src := &ComputedQuote{
|
||||
DebitAmount: &moneyv1.Money{Amount: "10", Currency: "USD"},
|
||||
}
|
||||
item := &QuoteComputationPlanItem{}
|
||||
|
||||
got := ensureComputedQuote(src, item)
|
||||
if got == nil {
|
||||
t.Fatalf("expected quote")
|
||||
}
|
||||
if got.ResolvedSettlementMode != paymentv1.SettlementMode_SETTLEMENT_FIX_SOURCE {
|
||||
t.Fatalf("unexpected default settlement mode: %s", got.ResolvedSettlementMode.String())
|
||||
}
|
||||
if got.ResolvedFeeTreatment != quotationv2.FeeTreatment_FEE_TREATMENT_ADD_TO_SOURCE {
|
||||
t.Fatalf("unexpected default fee treatment: %s", got.ResolvedFeeTreatment.String())
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,7 @@ func clonePaymentIntent(src model.PaymentIntent) model.PaymentIntent {
|
||||
FX: nil,
|
||||
FeePolicy: src.FeePolicy,
|
||||
SettlementMode: src.SettlementMode,
|
||||
FeeTreatment: src.FeeTreatment,
|
||||
SettlementCurrency: strings.ToUpper(strings.TrimSpace(src.SettlementCurrency)),
|
||||
Attributes: cloneStringMap(src.Attributes),
|
||||
Customer: src.Customer,
|
||||
|
||||
@@ -25,6 +25,7 @@ func modelIntentFromQuoteIntent(src *transfer_intent_hydrator.QuoteIntent) model
|
||||
RequiresFX: src.RequiresFX,
|
||||
Attributes: cloneStringMap(src.Attributes),
|
||||
SettlementMode: modelSettlementMode(src.SettlementMode),
|
||||
FeeTreatment: modelFeeTreatment(src.FeeTreatment),
|
||||
SettlementCurrency: settlementCurrency,
|
||||
}
|
||||
}
|
||||
@@ -106,3 +107,14 @@ func modelSettlementMode(mode transfer_intent_hydrator.QuoteSettlementMode) mode
|
||||
return model.SettlementModeFixSource
|
||||
}
|
||||
}
|
||||
|
||||
func modelFeeTreatment(value transfer_intent_hydrator.QuoteFeeTreatment) model.FeeTreatment {
|
||||
switch value {
|
||||
case transfer_intent_hydrator.QuoteFeeTreatmentDeductFromDestination:
|
||||
return model.FeeTreatmentDeductFromDestination
|
||||
case transfer_intent_hydrator.QuoteFeeTreatmentAddToSource:
|
||||
return model.FeeTreatmentAddToSource
|
||||
default:
|
||||
return model.FeeTreatmentAddToSource
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user