quotation service fixed
This commit is contained in:
@@ -75,10 +75,11 @@ type Rail string
|
||||
const (
|
||||
RailUnspecified Rail = "UNSPECIFIED"
|
||||
RailCrypto Rail = "CRYPTO"
|
||||
RailProviderSettlement Rail = "PROVIDER_SETTLEMENT"
|
||||
RailProviderSettlement Rail = "SETTLEMENT"
|
||||
RailLedger Rail = "LEDGER"
|
||||
RailCardPayout Rail = "CARD_PAYOUT"
|
||||
RailFiatOnRamp Rail = "FIAT_ONRAMP"
|
||||
RailCardPayout Rail = "CARD"
|
||||
RailFiatOnRamp Rail = "ONRAMP"
|
||||
RailFiatOffRamp Rail = "OFFRAMP"
|
||||
)
|
||||
|
||||
// RailOperation identifies an explicit action within a payment plan.
|
||||
|
||||
@@ -42,8 +42,8 @@ func (t *PaymentPlanTemplate) Normalize() {
|
||||
if t == nil {
|
||||
return
|
||||
}
|
||||
t.FromRail = Rail(strings.ToUpper(strings.TrimSpace(string(t.FromRail))))
|
||||
t.ToRail = Rail(strings.ToUpper(strings.TrimSpace(string(t.ToRail))))
|
||||
t.FromRail = normalizeRail(t.FromRail)
|
||||
t.ToRail = normalizeRail(t.ToRail)
|
||||
t.Network = strings.ToUpper(strings.TrimSpace(t.Network))
|
||||
if len(t.Steps) == 0 {
|
||||
return
|
||||
@@ -51,7 +51,7 @@ func (t *PaymentPlanTemplate) Normalize() {
|
||||
for i := range t.Steps {
|
||||
step := &t.Steps[i]
|
||||
step.StepID = strings.TrimSpace(step.StepID)
|
||||
step.Rail = Rail(strings.ToUpper(strings.TrimSpace(string(step.Rail))))
|
||||
step.Rail = normalizeRail(step.Rail)
|
||||
step.Operation = strings.ToLower(strings.TrimSpace(step.Operation))
|
||||
step.ReportVisibility = NormalizeReportVisibility(step.ReportVisibility)
|
||||
step.CommitPolicy = normalizeCommitPolicy(step.CommitPolicy)
|
||||
|
||||
62
api/payments/storage/model/rails.go
Normal file
62
api/payments/storage/model/rails.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package model
|
||||
|
||||
import "strings"
|
||||
|
||||
var supportedRails = map[Rail]struct{}{
|
||||
RailCrypto: {},
|
||||
RailProviderSettlement: {},
|
||||
RailLedger: {},
|
||||
RailCardPayout: {},
|
||||
RailFiatOnRamp: {},
|
||||
RailFiatOffRamp: {},
|
||||
}
|
||||
|
||||
// ParseRail canonicalizes string values into a Rail token.
|
||||
func ParseRail(value string) Rail {
|
||||
clean := strings.ToUpper(strings.TrimSpace(value))
|
||||
if clean == "" {
|
||||
return RailUnspecified
|
||||
}
|
||||
clean = strings.ReplaceAll(clean, "-", "_")
|
||||
clean = strings.ReplaceAll(clean, " ", "_")
|
||||
for strings.Contains(clean, "__") {
|
||||
clean = strings.ReplaceAll(clean, "__", "_")
|
||||
}
|
||||
|
||||
switch clean {
|
||||
case string(RailCrypto), "RAIL_CRYPTO":
|
||||
return RailCrypto
|
||||
case string(RailProviderSettlement), "PROVIDER_SETTLEMENT", "RAIL_SETTLEMENT", "RAIL_PROVIDER_SETTLEMENT":
|
||||
return RailProviderSettlement
|
||||
case string(RailLedger), "RAIL_LEDGER":
|
||||
return RailLedger
|
||||
case string(RailCardPayout), "CARD_PAYOUT", "RAIL_CARD", "RAIL_CARD_PAYOUT":
|
||||
return RailCardPayout
|
||||
case string(RailFiatOnRamp), "FIAT_ONRAMP", "RAIL_ONRAMP", "RAIL_FIAT_ONRAMP":
|
||||
return RailFiatOnRamp
|
||||
case string(RailFiatOffRamp), "FIAT_OFFRAMP", "RAIL_OFFRAMP", "RAIL_FIAT_OFFRAMP":
|
||||
return RailFiatOffRamp
|
||||
default:
|
||||
return RailUnspecified
|
||||
}
|
||||
}
|
||||
|
||||
// IsSupportedRail reports whether rail is recognized by payment planning.
|
||||
func IsSupportedRail(rail Rail) bool {
|
||||
_, ok := supportedRails[ParseRail(string(rail))]
|
||||
return ok
|
||||
}
|
||||
|
||||
func normalizeRail(value Rail) Rail {
|
||||
parsed := ParseRail(string(value))
|
||||
if parsed != RailUnspecified {
|
||||
return parsed
|
||||
}
|
||||
|
||||
clean := strings.ToUpper(strings.TrimSpace(string(value)))
|
||||
if clean == "" {
|
||||
return RailUnspecified
|
||||
}
|
||||
|
||||
return Rail(clean)
|
||||
}
|
||||
28
api/payments/storage/model/rails_test.go
Normal file
28
api/payments/storage/model/rails_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package model
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParseRail(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
input string
|
||||
want Rail
|
||||
}{
|
||||
{name: "crypto", input: "crypto", want: RailCrypto},
|
||||
{name: "settlement canonical", input: "SETTLEMENT", want: RailProviderSettlement},
|
||||
{name: "settlement legacy", input: "provider_settlement", want: RailProviderSettlement},
|
||||
{name: "card canonical", input: "card", want: RailCardPayout},
|
||||
{name: "card legacy", input: "card_payout", want: RailCardPayout},
|
||||
{name: "onramp", input: "fiat_onramp", want: RailFiatOnRamp},
|
||||
{name: "offramp", input: "fiat_offramp", want: RailFiatOffRamp},
|
||||
{name: "unknown", input: "telegram", want: RailUnspecified},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := ParseRail(tc.input); got != tc.want {
|
||||
t.Fatalf("ParseRail(%q) = %q, want %q", tc.input, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,8 @@ func (r *PaymentRoute) Normalize() {
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
r.FromRail = Rail(strings.ToUpper(strings.TrimSpace(string(r.FromRail))))
|
||||
r.ToRail = Rail(strings.ToUpper(strings.TrimSpace(string(r.ToRail))))
|
||||
r.FromRail = normalizeRail(r.FromRail)
|
||||
r.ToRail = normalizeRail(r.ToRail)
|
||||
r.Network = strings.ToUpper(strings.TrimSpace(r.Network))
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,7 @@ func (p *PlanTemplates) GetByID(ctx context.Context, id bson.ObjectID) (*model.P
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
entity.Normalize()
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
@@ -133,11 +134,15 @@ func (p *PlanTemplates) List(ctx context.Context, filter *model.PaymentPlanTempl
|
||||
|
||||
query := repository.Query()
|
||||
|
||||
if from := strings.ToUpper(strings.TrimSpace(string(filter.FromRail))); from != "" {
|
||||
query = query.Filter(repository.Field("fromRail"), from)
|
||||
if from := normalizedRailFilterValues(filter.FromRail); len(from) == 1 {
|
||||
query = query.Filter(repository.Field("fromRail"), from[0])
|
||||
} else if len(from) > 1 {
|
||||
query = query.In(repository.Field("fromRail"), stringSliceToAny(from)...)
|
||||
}
|
||||
if to := strings.ToUpper(strings.TrimSpace(string(filter.ToRail))); to != "" {
|
||||
query = query.Filter(repository.Field("toRail"), to)
|
||||
if to := normalizedRailFilterValues(filter.ToRail); len(to) == 1 {
|
||||
query = query.Filter(repository.Field("toRail"), to[0])
|
||||
} else if len(to) > 1 {
|
||||
query = query.In(repository.Field("toRail"), stringSliceToAny(to)...)
|
||||
}
|
||||
if network := strings.ToUpper(strings.TrimSpace(filter.Network)); network != "" {
|
||||
query = query.Filter(repository.Field("network"), network)
|
||||
@@ -152,6 +157,7 @@ func (p *PlanTemplates) List(ctx context.Context, filter *model.PaymentPlanTempl
|
||||
if err := cur.Decode(item); err != nil {
|
||||
return err
|
||||
}
|
||||
item.Normalize()
|
||||
templates = append(templates, item)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ func (r *Routes) GetByID(ctx context.Context, id bson.ObjectID) (*model.PaymentR
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
entity.Normalize()
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
@@ -130,11 +131,15 @@ func (r *Routes) List(ctx context.Context, filter *model.PaymentRouteFilter) (*m
|
||||
|
||||
query := repository.Query()
|
||||
|
||||
if from := strings.ToUpper(strings.TrimSpace(string(filter.FromRail))); from != "" {
|
||||
query = query.Filter(repository.Field("fromRail"), from)
|
||||
if from := normalizedRailFilterValues(filter.FromRail); len(from) == 1 {
|
||||
query = query.Filter(repository.Field("fromRail"), from[0])
|
||||
} else if len(from) > 1 {
|
||||
query = query.In(repository.Field("fromRail"), stringSliceToAny(from)...)
|
||||
}
|
||||
if to := strings.ToUpper(strings.TrimSpace(string(filter.ToRail))); to != "" {
|
||||
query = query.Filter(repository.Field("toRail"), to)
|
||||
if to := normalizedRailFilterValues(filter.ToRail); len(to) == 1 {
|
||||
query = query.Filter(repository.Field("toRail"), to[0])
|
||||
} else if len(to) > 1 {
|
||||
query = query.In(repository.Field("toRail"), stringSliceToAny(to)...)
|
||||
}
|
||||
if network := strings.ToUpper(strings.TrimSpace(filter.Network)); network != "" {
|
||||
query = query.Filter(repository.Field("network"), network)
|
||||
@@ -149,6 +154,7 @@ func (r *Routes) List(ctx context.Context, filter *model.PaymentRouteFilter) (*m
|
||||
if err := cur.Decode(item); err != nil {
|
||||
return err
|
||||
}
|
||||
item.Normalize()
|
||||
routes = append(routes, item)
|
||||
return nil
|
||||
}
|
||||
@@ -163,3 +169,38 @@ func (r *Routes) List(ctx context.Context, filter *model.PaymentRouteFilter) (*m
|
||||
}
|
||||
|
||||
var _ storage.RoutesStore = (*Routes)(nil)
|
||||
|
||||
func normalizedRailFilterValues(rail model.Rail) []string {
|
||||
clean := strings.ToUpper(strings.TrimSpace(string(rail)))
|
||||
if clean == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if parsed := model.ParseRail(string(rail)); parsed != model.RailUnspecified {
|
||||
switch parsed {
|
||||
case model.RailCrypto:
|
||||
return []string{string(model.RailCrypto), "RAIL_CRYPTO"}
|
||||
case model.RailProviderSettlement:
|
||||
return []string{string(model.RailProviderSettlement), "PROVIDER_SETTLEMENT", "RAIL_SETTLEMENT", "RAIL_PROVIDER_SETTLEMENT"}
|
||||
case model.RailLedger:
|
||||
return []string{string(model.RailLedger), "RAIL_LEDGER"}
|
||||
case model.RailCardPayout:
|
||||
return []string{string(model.RailCardPayout), "CARD_PAYOUT", "RAIL_CARD", "RAIL_CARD_PAYOUT"}
|
||||
case model.RailFiatOnRamp:
|
||||
return []string{string(model.RailFiatOnRamp), "FIAT_ONRAMP", "RAIL_ONRAMP", "RAIL_FIAT_ONRAMP"}
|
||||
case model.RailFiatOffRamp:
|
||||
return []string{string(model.RailFiatOffRamp), "FIAT_OFFRAMP", "RAIL_OFFRAMP", "RAIL_FIAT_OFFRAMP"}
|
||||
default:
|
||||
return []string{string(parsed)}
|
||||
}
|
||||
}
|
||||
return []string{clean}
|
||||
}
|
||||
|
||||
func stringSliceToAny(values []string) []any {
|
||||
out := make([]any, 0, len(values))
|
||||
for _, value := range values {
|
||||
out = append(out, value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user