mirror of
https://github.com/valitydev/hellgate.git
synced 2024-11-06 02:45:20 +00:00
IMP-171: Add route blacklist check (#119)
* added without tests * fixed * added tests * bumped, fixed, added explanation * fixed explanations * bumped cache * fixed explanation * fixed * fixed
This commit is contained in:
parent
578bbc8571
commit
872e076d33
2
.github/workflows/erlang-checks.yaml
vendored
2
.github/workflows/erlang-checks.yaml
vendored
@ -38,4 +38,4 @@ jobs:
|
||||
thrift-version: ${{ needs.setup.outputs.thrift-version }}
|
||||
run-ct-with-compose: true
|
||||
use-coveralls: true
|
||||
cache-version: v5
|
||||
cache-version: v6
|
||||
|
@ -1,10 +1,12 @@
|
||||
-module(hg_inspector).
|
||||
|
||||
-export([check_blacklist/1]).
|
||||
-export([inspect/4]).
|
||||
|
||||
-export([compare_risk_score/2]).
|
||||
|
||||
-export_type([risk_score/0]).
|
||||
-export_type([blacklist_context/0]).
|
||||
|
||||
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
|
||||
-include_lib("damsel/include/dmsl_proxy_inspector_thrift.hrl").
|
||||
@ -15,6 +17,48 @@
|
||||
-type inspector() :: dmsl_domain_thrift:'Inspector'().
|
||||
-type risk_score() :: dmsl_domain_thrift:'RiskScore'().
|
||||
-type risk_magnitude() :: integer().
|
||||
-type domain_revision() :: dmsl_domain_thrift:'DataRevision'().
|
||||
|
||||
-type blacklist_context() :: #{
|
||||
route => hg_route:t(),
|
||||
revision := domain_revision(),
|
||||
token => binary(),
|
||||
inspector := inspector()
|
||||
}.
|
||||
|
||||
-spec check_blacklist(blacklist_context()) -> boolean().
|
||||
check_blacklist(#{
|
||||
route := Route,
|
||||
revision := Revision,
|
||||
token := Token,
|
||||
inspector := #domain_Inspector{
|
||||
proxy = Proxy
|
||||
}
|
||||
}) when Token =/= undefined ->
|
||||
#domain_ProviderRef{id = ProviderID} = hg_route:provider_ref(Route),
|
||||
#domain_TerminalRef{id = TerminalID} = hg_route:terminal_ref(Route),
|
||||
Context = #proxy_inspector_BlackListContext{
|
||||
first_id = genlib:to_binary(ProviderID),
|
||||
second_id = genlib:to_binary(TerminalID),
|
||||
field_name = <<"CARD_TOKEN">>,
|
||||
value = Token
|
||||
},
|
||||
Result = issue_call(
|
||||
'IsBlacklisted',
|
||||
{Context},
|
||||
hg_proxy:get_call_options(
|
||||
Proxy,
|
||||
Revision
|
||||
)
|
||||
),
|
||||
case Result of
|
||||
{ok, Check} when is_atom(Check) ->
|
||||
Check;
|
||||
{exception, Error} ->
|
||||
error(Error)
|
||||
end;
|
||||
check_blacklist(_Ctx) ->
|
||||
false.
|
||||
|
||||
-spec inspect(shop(), invoice(), payment(), inspector()) -> risk_score() | no_return().
|
||||
inspect(
|
||||
@ -113,6 +157,9 @@ get_payment_info(
|
||||
payment = ProxyPayment
|
||||
}.
|
||||
|
||||
issue_call(Func, Args, CallOpts) ->
|
||||
issue_call(Func, Args, CallOpts, undefined, undefined).
|
||||
|
||||
issue_call(Func, Args, CallOpts, undefined, _DeadLine) ->
|
||||
% Do not set custom deadline without fallback risk score
|
||||
hg_woody_wrapper:call(proxy_inspector, Func, Args, CallOpts);
|
||||
|
@ -813,6 +813,8 @@ log_rejected_routes(limit_misconfiguration, Routes, _VS) ->
|
||||
?LOG_MD(warning, "Limiter hold error caused route candidates to be rejected: ~p", [Routes]);
|
||||
log_rejected_routes(limit_overflow, Routes, _VS) ->
|
||||
?LOG_MD(notice, "Limit overflow caused route candidates to be rejected: ~p", [Routes]);
|
||||
log_rejected_routes(in_blacklist, Routes, _VS) ->
|
||||
?LOG_MD(notice, "Route candidates are blacklisted: ~p", [Routes]);
|
||||
log_rejected_routes(adapter_unavailable, Routes, _VS) ->
|
||||
?LOG_MD(notice, "Adapter unavailability caused route candidates to be rejected: ~p", [Routes]);
|
||||
log_rejected_routes(provider_conversion_is_too_low, Routes, _VS) ->
|
||||
@ -1968,6 +1970,7 @@ run_routing_decision_pipeline(Ctx0, VS, St) ->
|
||||
%% accounted for in `St`.
|
||||
fun(Ctx) -> filter_routes_with_limit_hold(Ctx, VS, get_iter(St) + 1, St) end,
|
||||
fun(Ctx) -> filter_routes_by_limit_overflow(Ctx, VS, St) end,
|
||||
fun(Ctx) -> hg_routing:filter_by_blacklist(Ctx, build_blacklist_context(St)) end,
|
||||
fun hg_routing:filter_by_critical_provider_status/1,
|
||||
fun hg_routing:choose_route_with_ctx/1
|
||||
]
|
||||
@ -2023,6 +2026,28 @@ build_routing_context(PaymentInstitution, VS, Revision, St) ->
|
||||
gather_routes(PaymentInstitution, VS, Revision, St)
|
||||
end.
|
||||
|
||||
build_blacklist_context(St) ->
|
||||
Revision = get_payment_revision(St),
|
||||
#domain_InvoicePayment{payer = Payer} = get_payment(St),
|
||||
Token =
|
||||
case get_payer_payment_tool(Payer) of
|
||||
{bank_card, #domain_BankCard{token = CardToken}} ->
|
||||
CardToken;
|
||||
_ ->
|
||||
undefined
|
||||
end,
|
||||
Opts = get_opts(St),
|
||||
VS1 = get_varset(St, #{}),
|
||||
PaymentInstitutionRef = get_payment_institution_ref(Opts),
|
||||
PaymentInstitution = hg_payment_institution:compute_payment_institution(PaymentInstitutionRef, VS1, Revision),
|
||||
InspectorRef = get_selector_value(inspector, PaymentInstitution#domain_PaymentInstitution.inspector),
|
||||
Inspector = hg_domain:get(Revision, {inspector, InspectorRef}),
|
||||
#{
|
||||
revision => Revision,
|
||||
token => Token,
|
||||
inspector => Inspector
|
||||
}.
|
||||
|
||||
filter_attempted_routes(Ctx, #st{routes = AttemptedRoutes}) ->
|
||||
lists:foldr(
|
||||
fun(R, C) ->
|
||||
|
@ -16,6 +16,31 @@ get_service_spec() ->
|
||||
{"/test/proxy/inspector/dummy", {dmsl_proxy_inspector_thrift, 'InspectorProxy'}}.
|
||||
|
||||
-spec handle_function(woody:func(), woody:args(), hg_woody_service_wrapper:handler_opts()) -> term() | no_return().
|
||||
handle_function(
|
||||
'IsBlacklisted',
|
||||
{#proxy_inspector_BlackListContext{
|
||||
value = <<"inspector_fail_first">>,
|
||||
second_id = <<"1">>
|
||||
}},
|
||||
_Options
|
||||
) ->
|
||||
true;
|
||||
handle_function(
|
||||
'IsBlacklisted',
|
||||
{#proxy_inspector_BlackListContext{
|
||||
value = <<"inspector_fail_all">>
|
||||
}},
|
||||
_Options
|
||||
) ->
|
||||
true;
|
||||
handle_function(
|
||||
'IsBlacklisted',
|
||||
{#proxy_inspector_BlackListContext{
|
||||
value = _Token
|
||||
}},
|
||||
_Options
|
||||
) ->
|
||||
false;
|
||||
handle_function(
|
||||
'InspectPayment',
|
||||
{#proxy_inspector_Context{
|
||||
|
@ -282,6 +282,12 @@ process_payment(?processed(), undefined, PaymentInfo, CtxOpts, _) ->
|
||||
no_preauth ->
|
||||
%% simple workflow without 3DS
|
||||
maybe_fail(PaymentInfo, CtxOpts, result(?sleep(0), <<"sleeping">>));
|
||||
inspector_fail_first ->
|
||||
%% simple workflow without 3DS
|
||||
result(?sleep(0), <<"sleeping">>);
|
||||
inspector_fail_all ->
|
||||
%% simple workflow without 3DS
|
||||
result(?sleep(0), <<"sleeping">>);
|
||||
empty_cvv ->
|
||||
%% simple workflow without 3DS
|
||||
result(?sleep(0), <<"sleeping">>);
|
||||
@ -335,6 +341,8 @@ process_payment(?processed(), undefined, PaymentInfo, CtxOpts, _) ->
|
||||
process_payment(?processed(), <<"sleeping">>, PaymentInfo, CtxOpts, _) ->
|
||||
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
|
||||
case get_payment_info_scenario(PaymentInfo) of
|
||||
inspector_fail_first ->
|
||||
finish(success(PaymentInfo), mk_trx(TrxID, PaymentInfo));
|
||||
change_cash_increase ->
|
||||
finish(success(PaymentInfo, get_payment_increased_cost(PaymentInfo)), mk_trx(TrxID, PaymentInfo));
|
||||
change_cash_decrease ->
|
||||
@ -651,6 +659,10 @@ get_payment_tool_scenario({'bank_card', #domain_BankCard{token = <<"no_preauth_t
|
||||
no_preauth_timeout_failure;
|
||||
get_payment_tool_scenario({'bank_card', #domain_BankCard{token = <<"no_preauth_suspend_default">>}}) ->
|
||||
no_preauth_suspend_default;
|
||||
get_payment_tool_scenario({'bank_card', #domain_BankCard{token = <<"inspector_fail_first">>}}) ->
|
||||
inspector_fail_first;
|
||||
get_payment_tool_scenario({'bank_card', #domain_BankCard{token = <<"inspector_fail_all">>}}) ->
|
||||
inspector_fail_all;
|
||||
get_payment_tool_scenario({'bank_card', #domain_BankCard{token = <<"empty_cvv">>}}) ->
|
||||
empty_cvv;
|
||||
get_payment_tool_scenario({'bank_card', #domain_BankCard{token = <<"preauth_3ds:timeout=", Timeout/binary>>}}) ->
|
||||
@ -736,6 +748,10 @@ make_payment_tool(Code, PSys) when
|
||||
Code =:= unexpected_failure_no_trx
|
||||
->
|
||||
?SESSION42(make_bank_card_payment_tool(atom_to_binary(Code, utf8), PSys));
|
||||
make_payment_tool(inspector_fail_first, PSys) ->
|
||||
?SESSION42(make_bank_card_payment_tool(<<"inspector_fail_first">>, PSys));
|
||||
make_payment_tool(inspector_fail_all, PSys) ->
|
||||
?SESSION42(make_bank_card_payment_tool(<<"inspector_fail_all">>, PSys));
|
||||
make_payment_tool(empty_cvv, PSys) ->
|
||||
{_, BCard} = make_bank_card_payment_tool(<<"empty_cvv">>, PSys),
|
||||
?SESSION42({bank_card, BCard#domain_BankCard{is_cvv_empty = true}});
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
-export([payment_start_idempotency/1]).
|
||||
-export([payment_success/1]).
|
||||
-export([payment_w_first_blacklisted_success/1]).
|
||||
-export([payment_w_all_blacklisted/1]).
|
||||
-export([register_payment_success/1]).
|
||||
-export([register_payment_customer_payer_success/1]).
|
||||
-export([payment_success_additional_info/1]).
|
||||
@ -51,6 +53,8 @@ groups() ->
|
||||
{payments, [parallel], [
|
||||
payment_start_idempotency,
|
||||
payment_success,
|
||||
payment_w_first_blacklisted_success,
|
||||
payment_w_all_blacklisted,
|
||||
register_payment_success,
|
||||
register_payment_customer_payer_success,
|
||||
payment_success_additional_info,
|
||||
@ -189,6 +193,54 @@ payment_success(C) ->
|
||||
Trx
|
||||
).
|
||||
|
||||
-spec payment_w_first_blacklisted_success(config()) -> test_return().
|
||||
payment_w_first_blacklisted_success(C) ->
|
||||
Client = cfg(client, C),
|
||||
InvoiceID = start_invoice(<<"rubberduck">>, make_due_date(10), 42000, C),
|
||||
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(inspector_fail_first, ?pmt_sys(<<"visa-ref">>)),
|
||||
PaymentParams = make_payment_params(PaymentTool, Session, instant),
|
||||
PaymentID = process_payment(InvoiceID, PaymentParams, Client),
|
||||
PaymentID = await_payment_capture(InvoiceID, PaymentID, Client),
|
||||
?invoice_state(
|
||||
?invoice_w_status(?invoice_paid()),
|
||||
[_PaymentSt]
|
||||
) = hg_client_invoicing:get(InvoiceID, Client),
|
||||
_Explanation =
|
||||
#payproc_InvoicePaymentExplanation{
|
||||
explained_routes = [
|
||||
#payproc_InvoicePaymentRouteExplanation{
|
||||
route = ?route(?prv(1), ?trm(2)),
|
||||
is_chosen = true
|
||||
},
|
||||
#payproc_InvoicePaymentRouteExplanation{
|
||||
route = ?route(?prv(1), ?trm(1)),
|
||||
is_chosen = false,
|
||||
rejection_description = Desc
|
||||
}
|
||||
]
|
||||
} = hg_client_invoicing:explain_route(InvoiceID, PaymentID, Client),
|
||||
?assertEqual(
|
||||
<<"Route was blacklisted {domain_PaymentRoute,{domain_ProviderRef,1},{domain_TerminalRef,1}}.">>, Desc
|
||||
).
|
||||
|
||||
-spec payment_w_all_blacklisted(config()) -> test_return().
|
||||
payment_w_all_blacklisted(C) ->
|
||||
Client = cfg(client, C),
|
||||
InvoiceID = start_invoice(<<"rubberduck">>, make_due_date(10), 42000, C),
|
||||
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(inspector_fail_all, ?pmt_sys(<<"visa-ref">>)),
|
||||
PaymentParams = make_payment_params(PaymentTool, Session, instant),
|
||||
?payment_state(?payment(PaymentID)) = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_RiskScore)),
|
||||
?payment_ev(PaymentID, ?route_changed(_Route)),
|
||||
?payment_ev(PaymentID, ?payment_rollback_started({failure, _Failure}))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
?invoice_state(
|
||||
?invoice_w_status(?invoice_unpaid()),
|
||||
[_PaymentSt]
|
||||
) = hg_client_invoicing:get(InvoiceID, Client).
|
||||
|
||||
-spec register_payment_success(config()) -> test_return().
|
||||
register_payment_success(C) ->
|
||||
Client = cfg(client, C),
|
||||
@ -580,7 +632,7 @@ construct_domain_fixture() ->
|
||||
allocations = #domain_PaymentAllocationServiceTerms{
|
||||
allow = {constant, true}
|
||||
},
|
||||
attempt_limit = {value, #domain_AttemptLimit{attempts = 2}}
|
||||
attempt_limit = {value, #domain_AttemptLimit{attempts = 1}}
|
||||
},
|
||||
recurrent_paytools = #domain_RecurrentPaytoolsServiceTerms{
|
||||
payment_methods =
|
||||
@ -623,7 +675,8 @@ construct_domain_fixture() ->
|
||||
?ruleset(1),
|
||||
<<"Policies">>,
|
||||
{candidates, [
|
||||
?candidate({constant, true}, ?trm(1))
|
||||
?candidate({constant, true}, ?trm(1)),
|
||||
?candidate({constant, true}, ?trm(2))
|
||||
]}
|
||||
),
|
||||
hg_ct_fixture:construct_payment_routing_ruleset(
|
||||
@ -809,6 +862,14 @@ construct_domain_fixture() ->
|
||||
provider_ref = ?prv(1)
|
||||
}
|
||||
}},
|
||||
{terminal, #domain_TerminalObject{
|
||||
ref = ?trm(2),
|
||||
data = #domain_Terminal{
|
||||
name = <<"Brominal 2">>,
|
||||
description = <<"Brominal 2">>,
|
||||
provider_ref = ?prv(1)
|
||||
}
|
||||
}},
|
||||
|
||||
hg_ct_fixture:construct_mobile_operator(?mob(<<"mts-ref">>), <<"mts mobile operator">>),
|
||||
hg_ct_fixture:construct_payment_service(?pmt_srv(<<"qiwi-ref">>), <<"qiwi payment service">>),
|
||||
|
@ -20,6 +20,7 @@
|
||||
%%
|
||||
|
||||
-export([filter_by_critical_provider_status/1]).
|
||||
-export([filter_by_blacklist/2]).
|
||||
-export([choose_route_with_ctx/1]).
|
||||
|
||||
%%
|
||||
@ -50,6 +51,7 @@
|
||||
-type route_groups_by_priority() :: #{{availability_condition(), terminal_priority_rating()} => [fail_rated_route()]}.
|
||||
|
||||
-type fail_rated_route() :: {hg_route:t(), provider_status()}.
|
||||
-type blacklisted_route() :: {hg_route:t(), boolean()}.
|
||||
|
||||
-type scored_route() :: {route_scores(), hg_route:t()}.
|
||||
|
||||
@ -83,6 +85,7 @@
|
||||
-export_type([route_predestination/0]).
|
||||
-export_type([route_choice_context/0]).
|
||||
-export_type([fail_rated_route/0]).
|
||||
-export_type([blacklisted_route/0]).
|
||||
-export_type([route_scores/0]).
|
||||
-export_type([limits/0]).
|
||||
-export_type([scores/0]).
|
||||
@ -106,6 +109,24 @@ filter_by_critical_provider_status(Ctx0) ->
|
||||
RoutesFailRates
|
||||
).
|
||||
|
||||
-spec filter_by_blacklist(T, hg_inspector:blacklist_context()) -> T when T :: hg_routing_ctx:t().
|
||||
filter_by_blacklist(Ctx, BlCtx) ->
|
||||
BlacklistedRoutes = check_routes(hg_routing_ctx:candidates(Ctx), BlCtx),
|
||||
lists:foldr(
|
||||
fun
|
||||
({R, true = Status}, C) ->
|
||||
R1 = hg_route:to_rejected_route(R, {'InBlackList', Status}),
|
||||
Ctx0 = hg_routing_ctx:reject(in_blacklist, R1, C),
|
||||
Scores0 = score_route(R),
|
||||
Scores1 = Scores0#domain_PaymentRouteScores{blacklist_condition = 1},
|
||||
hg_routing_ctx:add_route_scores({hg_route:to_payment_route(R), Scores1}, Ctx0);
|
||||
({_R, _ProviderStatus}, C) ->
|
||||
C
|
||||
end,
|
||||
Ctx,
|
||||
BlacklistedRoutes
|
||||
).
|
||||
|
||||
-spec choose_route_with_ctx(T) -> T when T :: hg_routing_ctx:t().
|
||||
choose_route_with_ctx(Ctx) ->
|
||||
Candidates = hg_routing_ctx:candidates(Ctx),
|
||||
@ -281,6 +302,12 @@ compute_rule_set(RuleSetRef, VS, Revision) ->
|
||||
),
|
||||
RuleSet.
|
||||
|
||||
-spec check_routes([hg_route:t()], hg_inspector:blacklist_context()) -> [blacklisted_route()].
|
||||
check_routes([], _BlCtx) ->
|
||||
[];
|
||||
check_routes(Routes, BlCtx) ->
|
||||
[{R, hg_inspector:check_blacklist(BlCtx#{route => R})} || R <- Routes].
|
||||
|
||||
-spec rate_routes([hg_route:t()]) -> [fail_rated_route()].
|
||||
rate_routes(Routes) ->
|
||||
score_routes_with_fault_detector(Routes).
|
||||
@ -451,7 +478,7 @@ calc_random_condition(StartFrom, Random, [FailRatedRoute | Rest], Routes) ->
|
||||
score_routes_map(Routes) ->
|
||||
lists:foldl(
|
||||
fun({Route, _} = FailRatedRoute, Acc) ->
|
||||
Acc#{hg_route:to_payment_route(Route) => score_route(FailRatedRoute)}
|
||||
Acc#{hg_route:to_payment_route(Route) => score_route_ext(FailRatedRoute)}
|
||||
end,
|
||||
#{},
|
||||
Routes
|
||||
@ -459,24 +486,30 @@ score_routes_map(Routes) ->
|
||||
|
||||
-spec score_routes([fail_rated_route()]) -> [scored_route()].
|
||||
score_routes(Routes) ->
|
||||
[{score_route(FailRatedRoute), Route} || {Route, _} = FailRatedRoute <- Routes].
|
||||
[{score_route_ext(FailRatedRoute), Route} || {Route, _} = FailRatedRoute <- Routes].
|
||||
|
||||
score_route({Route, ProviderStatus}) ->
|
||||
score_route_ext({Route, ProviderStatus}) ->
|
||||
{AvailabilityStatus, ConversionStatus} = ProviderStatus,
|
||||
{AvailabilityCondition, Availability} = get_availability_score(AvailabilityStatus),
|
||||
{ConversionCondition, Conversion} = get_conversion_score(ConversionStatus),
|
||||
Scores = score_route(Route),
|
||||
Scores#domain_PaymentRouteScores{
|
||||
availability_condition = AvailabilityCondition,
|
||||
conversion_condition = ConversionCondition,
|
||||
availability = Availability,
|
||||
conversion = Conversion
|
||||
}.
|
||||
|
||||
score_route(Route) ->
|
||||
PriorityRate = hg_route:priority(Route),
|
||||
RandomCondition = hg_route:weight(Route),
|
||||
Pin = hg_route:pin(Route),
|
||||
PinHash = erlang:phash2(Pin),
|
||||
{AvailabilityStatus, ConversionStatus} = ProviderStatus,
|
||||
{AvailabilityCondition, Availability} = get_availability_score(AvailabilityStatus),
|
||||
{ConversionCondition, Conversion} = get_conversion_score(ConversionStatus),
|
||||
#domain_PaymentRouteScores{
|
||||
availability_condition = AvailabilityCondition,
|
||||
conversion_condition = ConversionCondition,
|
||||
terminal_priority_rating = PriorityRate,
|
||||
route_pin = PinHash,
|
||||
random_condition = RandomCondition,
|
||||
availability = Availability,
|
||||
conversion = Conversion
|
||||
blacklist_condition = 0
|
||||
}.
|
||||
|
||||
get_availability_score({alive, FailRate}) -> {1, 1.0 - FailRate};
|
||||
|
@ -22,11 +22,13 @@
|
||||
-export([stash_route_limits/2]).
|
||||
-export([route_scores/1]).
|
||||
-export([stash_route_scores/2]).
|
||||
-export([add_route_scores/2]).
|
||||
|
||||
-type rejection_group() :: atom().
|
||||
-type error() :: {atom(), _Description}.
|
||||
-type route_limits() :: hg_routing:limits().
|
||||
-type route_scores() :: hg_routing:scores().
|
||||
-type one_route_scores() :: {hg_route:payment_route(), hg_routing:route_scores()}.
|
||||
|
||||
-type t() :: #{
|
||||
initial_candidates := [hg_route:t()],
|
||||
@ -173,9 +175,15 @@ route_scores(Ctx) ->
|
||||
maps:get(route_scores, Ctx, undefined).
|
||||
|
||||
-spec stash_route_scores(route_scores(), t()) -> t().
|
||||
stash_route_scores(RouteScoresNew, Ctx = #{route_scores := RouteScores}) ->
|
||||
Ctx#{route_scores => maps:merge(RouteScores, RouteScoresNew)};
|
||||
stash_route_scores(RouteScores, Ctx) ->
|
||||
Ctx#{route_scores => RouteScores}.
|
||||
|
||||
-spec add_route_scores(one_route_scores(), t()) -> t().
|
||||
add_route_scores({PR, Scores}, Ctx) ->
|
||||
Ctx#{route_scores => #{PR => Scores}}.
|
||||
|
||||
%%
|
||||
|
||||
latest_rejected_routes(#{latest_rejection := ReasonGroup, rejections := Rejections}) ->
|
||||
|
@ -139,6 +139,11 @@ candidate_rejection_explanation(
|
||||
<<"We only know about limits for this route, but no limit",
|
||||
" was reached, if you see this message contact developer.">>,
|
||||
check_route_limits(RouteLimits, IfEmpty);
|
||||
candidate_rejection_explanation(
|
||||
R = #{scores := #domain_PaymentRouteScores{blacklist_condition = 1}},
|
||||
_
|
||||
) ->
|
||||
check_route_blacklisted(R);
|
||||
candidate_rejection_explanation(
|
||||
#{scores := RouteScores, limits := RouteLimits},
|
||||
#{scores := ChosenScores}
|
||||
@ -152,12 +157,13 @@ candidate_rejection_explanation(
|
||||
IfEmpty = <<"No explanation for rejection can be found. Check in with developer.">>,
|
||||
check_route_limits(RouteLimits, IfEmpty);
|
||||
candidate_rejection_explanation(
|
||||
#{scores := RouteScores, limits := RouteLimits},
|
||||
R = #{scores := RouteScores, limits := RouteLimits},
|
||||
#{scores := ChosenScores}
|
||||
) when RouteScores < ChosenScores ->
|
||||
Explanation0 = check_route_scores(RouteScores, ChosenScores),
|
||||
Explanation1 = check_route_limits(RouteLimits, <<"">>),
|
||||
genlib_string:join(<<" ">>, [Explanation0, Explanation1]).
|
||||
Explanation0 = check_route_blacklisted(R),
|
||||
Explanation1 = check_route_scores(RouteScores, ChosenScores),
|
||||
Explanation2 = check_route_limits(RouteLimits, <<"">>),
|
||||
genlib_string:join(<<" ">>, [Explanation0, Explanation1, Explanation2]).
|
||||
|
||||
check_route_limits(RouteLimits, IfEmpty) ->
|
||||
case check_route_limits(RouteLimits) of
|
||||
@ -261,6 +267,11 @@ check_route_scores(
|
||||
) when Cv0 < Cv1 ->
|
||||
format("Conversion is less than in chosen route ~p < ~p.", [Cv0, Cv1]).
|
||||
|
||||
check_route_blacklisted(#{route := R, scores := #domain_PaymentRouteScores{blacklist_condition = 1}}) ->
|
||||
format("Route was blacklisted ~w.", [R]);
|
||||
check_route_blacklisted(_) ->
|
||||
<<"">>.
|
||||
|
||||
gather_varset(Payment, Opts) ->
|
||||
#domain_InvoicePayment{
|
||||
cost = Cost,
|
||||
|
@ -21,7 +21,7 @@
|
||||
{<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},2},
|
||||
{<<"damsel">>,
|
||||
{git,"https://github.com/valitydev/damsel.git",
|
||||
{ref,"decfa45d7ce4b3c948957c6ddba34742aaa9fdc5"}},
|
||||
{ref,"f8e56c683617eca4e2ecb2ea6a8eec97c6c1dac9"}},
|
||||
0},
|
||||
{<<"dmt_client">>,
|
||||
{git,"https://github.com/valitydev/dmt-client.git",
|
||||
|
Loading…
Reference in New Issue
Block a user