Files
sendico/api/payments/quotation/internal/service/plan/plan_builder_routes.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
}