122 lines
3.2 KiB
Go
122 lines
3.2 KiB
Go
package plan
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/tech/sendico/payments/storage/model"
|
|
"github.com/tech/sendico/pkg/merrors"
|
|
)
|
|
|
|
func resolveRouteNetwork(attrs map[string]string, sourceNetwork, destNetwork string) (string, error) {
|
|
src := strings.ToUpper(strings.TrimSpace(sourceNetwork))
|
|
dst := strings.ToUpper(strings.TrimSpace(destNetwork))
|
|
if src != "" && dst != "" && !strings.EqualFold(src, dst) {
|
|
return "", merrors.InvalidArgument("plan builder: source and destination networks mismatch")
|
|
}
|
|
|
|
override := strings.ToUpper(strings.TrimSpace(attributeLookup(attrs,
|
|
"network",
|
|
"route_network",
|
|
"routeNetwork",
|
|
"source_network",
|
|
"sourceNetwork",
|
|
"destination_network",
|
|
"destinationNetwork",
|
|
)))
|
|
if override != "" {
|
|
if src != "" && !strings.EqualFold(src, override) {
|
|
return "", merrors.InvalidArgument("plan builder: source network does not match override")
|
|
}
|
|
if dst != "" && !strings.EqualFold(dst, override) {
|
|
return "", merrors.InvalidArgument("plan builder: destination network does not match override")
|
|
}
|
|
return override, nil
|
|
}
|
|
if src != "" {
|
|
return src, nil
|
|
}
|
|
if dst != "" {
|
|
return dst, nil
|
|
}
|
|
return "", nil
|
|
}
|
|
|
|
func selectRoute(ctx context.Context, routes RouteStore, sourceRail, destRail model.Rail, network string) (*model.PaymentRoute, error) {
|
|
if routes == nil {
|
|
return nil, merrors.InvalidArgument("plan builder: routes store is required")
|
|
}
|
|
enabled := true
|
|
result, err := routes.List(ctx, &model.PaymentRouteFilter{
|
|
FromRail: sourceRail,
|
|
ToRail: destRail,
|
|
Network: "",
|
|
IsEnabled: &enabled,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if result == nil || len(result.Items) == 0 {
|
|
return nil, merrors.InvalidArgument("plan builder: route not allowed")
|
|
}
|
|
candidates := make([]*model.PaymentRoute, 0, len(result.Items))
|
|
for _, route := range result.Items {
|
|
if route == nil || !route.IsEnabled {
|
|
continue
|
|
}
|
|
if route.FromRail != sourceRail || route.ToRail != destRail {
|
|
continue
|
|
}
|
|
if !routeMatchesNetwork(route, network) {
|
|
continue
|
|
}
|
|
candidates = append(candidates, route)
|
|
}
|
|
if len(candidates) == 0 {
|
|
return nil, merrors.InvalidArgument("plan builder: route not allowed")
|
|
}
|
|
sort.Slice(candidates, func(i, j int) bool {
|
|
pi := routePriority(candidates[i], network)
|
|
pj := routePriority(candidates[j], network)
|
|
if pi != pj {
|
|
return pi < pj
|
|
}
|
|
if candidates[i].Network != candidates[j].Network {
|
|
return candidates[i].Network < candidates[j].Network
|
|
}
|
|
return candidates[i].ID.Hex() < candidates[j].ID.Hex()
|
|
})
|
|
return candidates[0], nil
|
|
}
|
|
|
|
func routeMatchesNetwork(route *model.PaymentRoute, network string) bool {
|
|
if route == nil {
|
|
return false
|
|
}
|
|
routeNetwork := strings.ToUpper(strings.TrimSpace(route.Network))
|
|
net := strings.ToUpper(strings.TrimSpace(network))
|
|
if routeNetwork == "" {
|
|
return true
|
|
}
|
|
if net == "" {
|
|
return false
|
|
}
|
|
return strings.EqualFold(routeNetwork, net)
|
|
}
|
|
|
|
func routePriority(route *model.PaymentRoute, network string) int {
|
|
if route == nil {
|
|
return 2
|
|
}
|
|
routeNetwork := strings.ToUpper(strings.TrimSpace(route.Network))
|
|
net := strings.ToUpper(strings.TrimSpace(network))
|
|
if net != "" && strings.EqualFold(routeNetwork, net) {
|
|
return 0
|
|
}
|
|
if routeNetwork == "" {
|
|
return 1
|
|
}
|
|
return 2
|
|
}
|