mirror of
https://github.com/valitydev/hellgate.git
synced 2024-11-06 02:45:20 +00:00
TD-572: Get payment routes limit values (#79)
* TD-572. impelementation get_limit * TD-572: add test for get_limits * TD-572: fix formatting * TD-572: add test for exception * TD-572: change limits output format * TD-572: fix spec * TD-572: fix naming, add test --------- Co-authored-by: anatoliy.losev <losto@nix>
This commit is contained in:
parent
e87b1e2ccf
commit
9d46f1fbd7
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@ tags
|
||||
# make stuff
|
||||
/.image.*
|
||||
Makefile.env
|
||||
*.iml
|
||||
|
@ -241,7 +241,11 @@ handle_function_('Repair', {InvoiceID, Changes, Action, Params}, _Opts) ->
|
||||
repair(InvoiceID, {changes, Changes, Action, Params});
|
||||
handle_function_('RepairWithScenario', {InvoiceID, Scenario}, _Opts) ->
|
||||
_ = set_invoicing_meta(InvoiceID),
|
||||
repair(InvoiceID, {scenario, Scenario}).
|
||||
repair(InvoiceID, {scenario, Scenario});
|
||||
handle_function_('GetPaymentRoutesLimitValues', {InvoiceID, PaymentID}, _Opts) ->
|
||||
_ = set_invoicing_meta(InvoiceID, PaymentID),
|
||||
St = get_state(InvoiceID),
|
||||
hg_invoice_payment:get_limit_values(get_payment_session(PaymentID, St), get_payment_opts(St)).
|
||||
|
||||
maybe_allocation(undefined, _Cost, _MerchantTerms, _Party, _Shop) ->
|
||||
undefined;
|
||||
|
@ -83,6 +83,7 @@
|
||||
-export([create_session_event_context/3]).
|
||||
-export([add_session/3]).
|
||||
-export([accrue_status_timing/3]).
|
||||
-export([get_limit_values/2]).
|
||||
|
||||
%% Machine like
|
||||
|
||||
@ -205,6 +206,7 @@
|
||||
-type recurrent_paytool_service_terms() :: dmsl_domain_thrift:'RecurrentPaytoolsServiceTerms'().
|
||||
-type session() :: hg_session:t().
|
||||
-type payment_plan_id() :: hg_accounting:plan_id().
|
||||
-type route_limit_context() :: dmsl_payproc_thrift:'RouteLimitContext'().
|
||||
|
||||
-type opts() :: #{
|
||||
party => party(),
|
||||
@ -2243,6 +2245,26 @@ process_risk_score(Action, St) ->
|
||||
|
||||
-spec process_routing(action(), st()) -> machine_result().
|
||||
process_routing(Action, St) ->
|
||||
{PaymentInstitution, VS, Revision} = route_args(St),
|
||||
try
|
||||
AllRoutes = get_candidates(PaymentInstitution, VS, Revision, St),
|
||||
AvailableRoutes = filter_out_attempted_routes(AllRoutes, St),
|
||||
%% Since this is routing step then current attempt is not yet accounted for in `St`.
|
||||
Iter = get_iter(St) + 1,
|
||||
Events = handle_gathered_route_result(
|
||||
filter_limit_overflow_routes(AvailableRoutes, VS, Iter, St),
|
||||
[hg_routing:to_payment_route(R) || R <- AllRoutes],
|
||||
[hg_routing:to_payment_route(R) || R <- AvailableRoutes],
|
||||
Revision,
|
||||
St
|
||||
),
|
||||
{next, {Events, hg_machine_action:set_timeout(0, Action)}}
|
||||
catch
|
||||
throw:{no_route_found, Reason} ->
|
||||
handle_choose_route_error(Reason, [], St, Action)
|
||||
end.
|
||||
|
||||
route_args(St) ->
|
||||
Opts = get_opts(St),
|
||||
Revision = get_payment_revision(St),
|
||||
Payment = get_payment(St),
|
||||
@ -2253,29 +2275,15 @@ process_routing(Action, St) ->
|
||||
VS2 = collect_refund_varset(MerchantTerms#domain_PaymentsServiceTerms.refunds, PaymentTool, VS1),
|
||||
VS3 = collect_chargeback_varset(MerchantTerms#domain_PaymentsServiceTerms.chargebacks, VS2),
|
||||
PaymentInstitution = hg_payment_institution:compute_payment_institution(PaymentInstitutionRef, VS1, Revision),
|
||||
try
|
||||
{PaymentInstitution, VS3, Revision}.
|
||||
|
||||
get_candidates(PaymentInstitution, VS, Revision, St) ->
|
||||
Payer = get_payment_payer(St),
|
||||
AllRoutes =
|
||||
case get_predefined_route(Payer) of
|
||||
{ok, PaymentRoute} ->
|
||||
[hg_routing:from_payment_route(PaymentRoute)];
|
||||
undefined ->
|
||||
gather_routes(PaymentInstitution, VS3, Revision, St)
|
||||
end,
|
||||
AvailableRoutes = filter_out_attempted_routes(AllRoutes, St),
|
||||
%% Since this is routing step then current attempt is not yet accounted for in `St`.
|
||||
Iter = get_iter(St) + 1,
|
||||
Events = handle_gathered_route_result(
|
||||
filter_limit_overflow_routes(AvailableRoutes, VS3, Iter, St),
|
||||
[hg_routing:to_payment_route(R) || R <- AllRoutes],
|
||||
[hg_routing:to_payment_route(R) || R <- AvailableRoutes],
|
||||
Revision,
|
||||
St
|
||||
),
|
||||
{next, {Events, hg_machine_action:set_timeout(0, Action)}}
|
||||
catch
|
||||
throw:{no_route_found, Reason} ->
|
||||
handle_choose_route_error(Reason, [], St, Action)
|
||||
gather_routes(PaymentInstitution, VS, Revision, St)
|
||||
end.
|
||||
|
||||
filter_out_attempted_routes(Routes, #st{routes = AttemptedRoutes}) ->
|
||||
@ -3502,6 +3510,28 @@ accrue_status_timing(Name, Opts, #st{timings = Timings}) ->
|
||||
EventTime = define_event_timestamp(Opts),
|
||||
hg_timings:mark(Name, EventTime, hg_timings:accrue(Name, started, EventTime, Timings)).
|
||||
|
||||
-spec get_limit_values(st()) -> route_limit_context().
|
||||
get_limit_values(St) ->
|
||||
{PaymentInstitution, VS, Revision} = route_args(St),
|
||||
Routes = get_candidates(PaymentInstitution, VS, Revision, St),
|
||||
Payment = get_payment(St),
|
||||
Invoice = get_invoice(get_opts(St)),
|
||||
lists:foldl(
|
||||
fun(Route, Acc) ->
|
||||
PaymentRoute = hg_routing:to_payment_route(Route),
|
||||
ProviderTerms = hg_routing:get_payment_terms(PaymentRoute, VS, Revision),
|
||||
TurnoverLimits = get_turnover_limits(ProviderTerms),
|
||||
TurnoverLimitValues = hg_limiter:get_limit_values(TurnoverLimits, Invoice, Payment, PaymentRoute),
|
||||
Acc#{PaymentRoute => TurnoverLimitValues}
|
||||
end,
|
||||
#{},
|
||||
Routes
|
||||
).
|
||||
|
||||
-spec get_limit_values(st(), opts()) -> route_limit_context().
|
||||
get_limit_values(St, Opts) ->
|
||||
get_limit_values(St#st{opts = Opts}).
|
||||
|
||||
try_accrue_waiting_timing(Opts, #st{payment = Payment, timings = Timings}) ->
|
||||
case get_payment_flow(Payment) of
|
||||
?invoice_payment_flow_instant() ->
|
||||
|
@ -1,5 +1,6 @@
|
||||
-module(hg_limiter).
|
||||
|
||||
-include_lib("damsel/include/dmsl_payproc_thrift.hrl").
|
||||
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
|
||||
-include_lib("damsel/include/dmsl_base_thrift.hrl").
|
||||
-include_lib("limiter_proto/include/limproto_base_thrift.hrl").
|
||||
@ -14,6 +15,7 @@
|
||||
-type refund() :: hg_invoice_payment:domain_refund().
|
||||
-type cash() :: dmsl_domain_thrift:'Cash'().
|
||||
-type handling_flag() :: ignore_business_error.
|
||||
-type turnover_limit_value() :: dmsl_payproc_thrift:'TurnoverLimitValue'().
|
||||
|
||||
-type change_queue() :: [hg_limiter_client:limit_change()].
|
||||
|
||||
@ -25,6 +27,7 @@
|
||||
-export([commit_refund_limits/5]).
|
||||
-export([rollback_payment_limits/6]).
|
||||
-export([rollback_refund_limits/5]).
|
||||
-export([get_limit_values/4]).
|
||||
|
||||
-define(route(ProviderRef, TerminalRef), #domain_PaymentRoute{
|
||||
provider = ProviderRef,
|
||||
@ -39,6 +42,23 @@ get_turnover_limits({value, Limits}) ->
|
||||
get_turnover_limits(Ambiguous) ->
|
||||
error({misconfiguration, {'Could not reduce selector to a value', Ambiguous}}).
|
||||
|
||||
-spec get_limit_values([turnover_limit()], invoice(), payment(), route()) -> [turnover_limit_value()].
|
||||
get_limit_values(TurnoverLimits, Invoice, Payment, Route) ->
|
||||
Context = gen_limit_context(Invoice, Payment, Route),
|
||||
lists:foldl(
|
||||
fun(TurnoverLimit, Acc) ->
|
||||
#domain_TurnoverLimit{id = LimitID, domain_revision = Version} = TurnoverLimit,
|
||||
Clock = get_latest_clock(),
|
||||
Limit = hg_limiter_client:get(LimitID, Version, Clock, Context),
|
||||
#limiter_Limit{
|
||||
amount = LimiterAmount
|
||||
} = Limit,
|
||||
[#payproc_TurnoverLimitValue{limit = TurnoverLimit, value = LimiterAmount} | Acc]
|
||||
end,
|
||||
[],
|
||||
TurnoverLimits
|
||||
).
|
||||
|
||||
-spec check_limits([turnover_limit()], invoice(), payment(), route()) ->
|
||||
{ok, [hg_limiter_client:limit()]}
|
||||
| {error, {limit_overflow, [binary()]}}.
|
||||
|
@ -40,6 +40,7 @@
|
||||
-export([register_payment_customer_payer_success/1]).
|
||||
|
||||
-export([payment_limit_success/1]).
|
||||
-export([payment_routes_limit_values/1]).
|
||||
-export([register_payment_limit_success/1]).
|
||||
-export([payment_limit_other_shop_success/1]).
|
||||
-export([payment_limit_overflow/1]).
|
||||
@ -383,6 +384,7 @@ groups() ->
|
||||
|
||||
{operation_limits, [], [
|
||||
payment_limit_success,
|
||||
payment_routes_limit_values,
|
||||
register_payment_limit_success,
|
||||
payment_limit_other_shop_success,
|
||||
payment_limit_overflow,
|
||||
@ -1254,6 +1256,30 @@ payment_limit_success(C) ->
|
||||
[?payment_state(_Payment)]
|
||||
) = create_payment(PartyID, ShopID, 10000, Client, ?pmt_sys(<<"visa-ref">>)).
|
||||
|
||||
-spec payment_routes_limit_values(config()) -> test_return().
|
||||
payment_routes_limit_values(C) ->
|
||||
RootUrl = cfg(root_url, C),
|
||||
PartyClient = cfg(party_client, C),
|
||||
#{party_id := PartyID} = cfg(limits, C),
|
||||
ShopID = hg_ct_helper:create_shop(PartyID, ?cat(8), <<"RUB">>, ?tmpl(1), ?pinst(1), PartyClient),
|
||||
Client = hg_client_invoicing:start_link(hg_ct_helper:create_client(RootUrl)),
|
||||
|
||||
#payproc_Invoice{
|
||||
invoice = #domain_Invoice{id = InvoiceId},
|
||||
payments = [
|
||||
#payproc_InvoicePayment{payment = #domain_InvoicePayment{id = PaymentId}}
|
||||
]
|
||||
} = create_payment(PartyID, ShopID, 10000, Client, ?pmt_sys(<<"visa-ref">>)),
|
||||
Route = ?route(?prv(5), ?trm(12)),
|
||||
#{
|
||||
Route := [
|
||||
#payproc_TurnoverLimitValue{
|
||||
limit = #domain_TurnoverLimit{id = ?LIMIT_ID, upper_boundary = ?LIMIT_UPPER_BOUNDARY},
|
||||
value = 10000
|
||||
}
|
||||
]
|
||||
} = hg_client_invoicing:get_limit_values(InvoiceId, PaymentId, Client).
|
||||
|
||||
-spec register_payment_limit_success(config()) -> test_return().
|
||||
register_payment_limit_success(C0) ->
|
||||
Client = cfg(client, C0),
|
||||
|
@ -15,6 +15,7 @@
|
||||
-export([rescind/3]).
|
||||
-export([repair/5]).
|
||||
-export([repair_scenario/3]).
|
||||
-export([get_limit_values/3]).
|
||||
|
||||
-export([create_invoice_adjustment/3]).
|
||||
-export([get_invoice_adjustment/3]).
|
||||
@ -98,6 +99,8 @@
|
||||
-type event_range() :: dmsl_payproc_thrift:'EventRange'().
|
||||
-type party_revision_param() :: dmsl_payproc_thrift:'PartyRevisionParam'().
|
||||
|
||||
-type route_limit_context() :: dmsl_payproc_thrift:'RouteLimitContext'().
|
||||
|
||||
-spec start(hg_client_api:t()) -> pid().
|
||||
start(ApiClient) ->
|
||||
start(start, ApiClient).
|
||||
@ -150,6 +153,10 @@ repair(InvoiceID, Changes, Action, Params, Client) ->
|
||||
repair_scenario(InvoiceID, Scenario, Client) ->
|
||||
map_result_error(gen_server:call(Client, {call, 'RepairWithScenario', [InvoiceID, Scenario]})).
|
||||
|
||||
-spec get_limit_values(invoice_id(), payment_id(), pid()) -> route_limit_context() | woody_error:business_error().
|
||||
get_limit_values(InvoiceID, PaymentID, Client) ->
|
||||
map_result_error(gen_server:call(Client, {call, 'GetPaymentRoutesLimitValues', [InvoiceID, PaymentID]})).
|
||||
|
||||
-spec create_invoice_adjustment(invoice_id(), invoice_adjustment_params(), pid()) ->
|
||||
invoice_adjustment() | woody_error:business_error().
|
||||
create_invoice_adjustment(InvoiceID, Params, Client) ->
|
||||
|
@ -17,7 +17,7 @@
|
||||
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.11.0">>},2},
|
||||
{<<"damsel">>,
|
||||
{git,"https://github.com/valitydev/damsel.git",
|
||||
{ref,"03bf41075c39b6731c5ed200d5c4b0faaee9d937"}},
|
||||
{ref,"52dbefd54fd68d0c04f8ded5734b27635e939c60"}},
|
||||
0},
|
||||
{<<"dmt_client">>,
|
||||
{git,"https://github.com/valitydev/dmt-client.git",
|
||||
|
Loading…
Reference in New Issue
Block a user