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
|
# make stuff
|
||||||
/.image.*
|
/.image.*
|
||||||
Makefile.env
|
Makefile.env
|
||||||
|
*.iml
|
||||||
|
@ -241,7 +241,11 @@ handle_function_('Repair', {InvoiceID, Changes, Action, Params}, _Opts) ->
|
|||||||
repair(InvoiceID, {changes, Changes, Action, Params});
|
repair(InvoiceID, {changes, Changes, Action, Params});
|
||||||
handle_function_('RepairWithScenario', {InvoiceID, Scenario}, _Opts) ->
|
handle_function_('RepairWithScenario', {InvoiceID, Scenario}, _Opts) ->
|
||||||
_ = set_invoicing_meta(InvoiceID),
|
_ = 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) ->
|
maybe_allocation(undefined, _Cost, _MerchantTerms, _Party, _Shop) ->
|
||||||
undefined;
|
undefined;
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
-export([create_session_event_context/3]).
|
-export([create_session_event_context/3]).
|
||||||
-export([add_session/3]).
|
-export([add_session/3]).
|
||||||
-export([accrue_status_timing/3]).
|
-export([accrue_status_timing/3]).
|
||||||
|
-export([get_limit_values/2]).
|
||||||
|
|
||||||
%% Machine like
|
%% Machine like
|
||||||
|
|
||||||
@ -205,6 +206,7 @@
|
|||||||
-type recurrent_paytool_service_terms() :: dmsl_domain_thrift:'RecurrentPaytoolsServiceTerms'().
|
-type recurrent_paytool_service_terms() :: dmsl_domain_thrift:'RecurrentPaytoolsServiceTerms'().
|
||||||
-type session() :: hg_session:t().
|
-type session() :: hg_session:t().
|
||||||
-type payment_plan_id() :: hg_accounting:plan_id().
|
-type payment_plan_id() :: hg_accounting:plan_id().
|
||||||
|
-type route_limit_context() :: dmsl_payproc_thrift:'RouteLimitContext'().
|
||||||
|
|
||||||
-type opts() :: #{
|
-type opts() :: #{
|
||||||
party => party(),
|
party => party(),
|
||||||
@ -2243,6 +2245,26 @@ process_risk_score(Action, St) ->
|
|||||||
|
|
||||||
-spec process_routing(action(), st()) -> machine_result().
|
-spec process_routing(action(), st()) -> machine_result().
|
||||||
process_routing(Action, St) ->
|
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),
|
Opts = get_opts(St),
|
||||||
Revision = get_payment_revision(St),
|
Revision = get_payment_revision(St),
|
||||||
Payment = get_payment(St),
|
Payment = get_payment(St),
|
||||||
@ -2253,29 +2275,15 @@ process_routing(Action, St) ->
|
|||||||
VS2 = collect_refund_varset(MerchantTerms#domain_PaymentsServiceTerms.refunds, PaymentTool, VS1),
|
VS2 = collect_refund_varset(MerchantTerms#domain_PaymentsServiceTerms.refunds, PaymentTool, VS1),
|
||||||
VS3 = collect_chargeback_varset(MerchantTerms#domain_PaymentsServiceTerms.chargebacks, VS2),
|
VS3 = collect_chargeback_varset(MerchantTerms#domain_PaymentsServiceTerms.chargebacks, VS2),
|
||||||
PaymentInstitution = hg_payment_institution:compute_payment_institution(PaymentInstitutionRef, VS1, Revision),
|
PaymentInstitution = hg_payment_institution:compute_payment_institution(PaymentInstitutionRef, VS1, Revision),
|
||||||
try
|
{PaymentInstitution, VS3, Revision}.
|
||||||
Payer = get_payment_payer(St),
|
|
||||||
AllRoutes =
|
get_candidates(PaymentInstitution, VS, Revision, St) ->
|
||||||
case get_predefined_route(Payer) of
|
Payer = get_payment_payer(St),
|
||||||
{ok, PaymentRoute} ->
|
case get_predefined_route(Payer) of
|
||||||
[hg_routing:from_payment_route(PaymentRoute)];
|
{ok, PaymentRoute} ->
|
||||||
undefined ->
|
[hg_routing:from_payment_route(PaymentRoute)];
|
||||||
gather_routes(PaymentInstitution, VS3, Revision, St)
|
undefined ->
|
||||||
end,
|
gather_routes(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, 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)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
filter_out_attempted_routes(Routes, #st{routes = AttemptedRoutes}) ->
|
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),
|
EventTime = define_event_timestamp(Opts),
|
||||||
hg_timings:mark(Name, EventTime, hg_timings:accrue(Name, started, EventTime, Timings)).
|
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}) ->
|
try_accrue_waiting_timing(Opts, #st{payment = Payment, timings = Timings}) ->
|
||||||
case get_payment_flow(Payment) of
|
case get_payment_flow(Payment) of
|
||||||
?invoice_payment_flow_instant() ->
|
?invoice_payment_flow_instant() ->
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
-module(hg_limiter).
|
-module(hg_limiter).
|
||||||
|
|
||||||
|
-include_lib("damsel/include/dmsl_payproc_thrift.hrl").
|
||||||
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
|
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
|
||||||
-include_lib("damsel/include/dmsl_base_thrift.hrl").
|
-include_lib("damsel/include/dmsl_base_thrift.hrl").
|
||||||
-include_lib("limiter_proto/include/limproto_base_thrift.hrl").
|
-include_lib("limiter_proto/include/limproto_base_thrift.hrl").
|
||||||
@ -14,6 +15,7 @@
|
|||||||
-type refund() :: hg_invoice_payment:domain_refund().
|
-type refund() :: hg_invoice_payment:domain_refund().
|
||||||
-type cash() :: dmsl_domain_thrift:'Cash'().
|
-type cash() :: dmsl_domain_thrift:'Cash'().
|
||||||
-type handling_flag() :: ignore_business_error.
|
-type handling_flag() :: ignore_business_error.
|
||||||
|
-type turnover_limit_value() :: dmsl_payproc_thrift:'TurnoverLimitValue'().
|
||||||
|
|
||||||
-type change_queue() :: [hg_limiter_client:limit_change()].
|
-type change_queue() :: [hg_limiter_client:limit_change()].
|
||||||
|
|
||||||
@ -25,6 +27,7 @@
|
|||||||
-export([commit_refund_limits/5]).
|
-export([commit_refund_limits/5]).
|
||||||
-export([rollback_payment_limits/6]).
|
-export([rollback_payment_limits/6]).
|
||||||
-export([rollback_refund_limits/5]).
|
-export([rollback_refund_limits/5]).
|
||||||
|
-export([get_limit_values/4]).
|
||||||
|
|
||||||
-define(route(ProviderRef, TerminalRef), #domain_PaymentRoute{
|
-define(route(ProviderRef, TerminalRef), #domain_PaymentRoute{
|
||||||
provider = ProviderRef,
|
provider = ProviderRef,
|
||||||
@ -39,6 +42,23 @@ get_turnover_limits({value, Limits}) ->
|
|||||||
get_turnover_limits(Ambiguous) ->
|
get_turnover_limits(Ambiguous) ->
|
||||||
error({misconfiguration, {'Could not reduce selector to a value', 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()) ->
|
-spec check_limits([turnover_limit()], invoice(), payment(), route()) ->
|
||||||
{ok, [hg_limiter_client:limit()]}
|
{ok, [hg_limiter_client:limit()]}
|
||||||
| {error, {limit_overflow, [binary()]}}.
|
| {error, {limit_overflow, [binary()]}}.
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
-export([register_payment_customer_payer_success/1]).
|
-export([register_payment_customer_payer_success/1]).
|
||||||
|
|
||||||
-export([payment_limit_success/1]).
|
-export([payment_limit_success/1]).
|
||||||
|
-export([payment_routes_limit_values/1]).
|
||||||
-export([register_payment_limit_success/1]).
|
-export([register_payment_limit_success/1]).
|
||||||
-export([payment_limit_other_shop_success/1]).
|
-export([payment_limit_other_shop_success/1]).
|
||||||
-export([payment_limit_overflow/1]).
|
-export([payment_limit_overflow/1]).
|
||||||
@ -383,6 +384,7 @@ groups() ->
|
|||||||
|
|
||||||
{operation_limits, [], [
|
{operation_limits, [], [
|
||||||
payment_limit_success,
|
payment_limit_success,
|
||||||
|
payment_routes_limit_values,
|
||||||
register_payment_limit_success,
|
register_payment_limit_success,
|
||||||
payment_limit_other_shop_success,
|
payment_limit_other_shop_success,
|
||||||
payment_limit_overflow,
|
payment_limit_overflow,
|
||||||
@ -1254,6 +1256,30 @@ payment_limit_success(C) ->
|
|||||||
[?payment_state(_Payment)]
|
[?payment_state(_Payment)]
|
||||||
) = create_payment(PartyID, ShopID, 10000, Client, ?pmt_sys(<<"visa-ref">>)).
|
) = 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().
|
-spec register_payment_limit_success(config()) -> test_return().
|
||||||
register_payment_limit_success(C0) ->
|
register_payment_limit_success(C0) ->
|
||||||
Client = cfg(client, C0),
|
Client = cfg(client, C0),
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
-export([rescind/3]).
|
-export([rescind/3]).
|
||||||
-export([repair/5]).
|
-export([repair/5]).
|
||||||
-export([repair_scenario/3]).
|
-export([repair_scenario/3]).
|
||||||
|
-export([get_limit_values/3]).
|
||||||
|
|
||||||
-export([create_invoice_adjustment/3]).
|
-export([create_invoice_adjustment/3]).
|
||||||
-export([get_invoice_adjustment/3]).
|
-export([get_invoice_adjustment/3]).
|
||||||
@ -98,6 +99,8 @@
|
|||||||
-type event_range() :: dmsl_payproc_thrift:'EventRange'().
|
-type event_range() :: dmsl_payproc_thrift:'EventRange'().
|
||||||
-type party_revision_param() :: dmsl_payproc_thrift:'PartyRevisionParam'().
|
-type party_revision_param() :: dmsl_payproc_thrift:'PartyRevisionParam'().
|
||||||
|
|
||||||
|
-type route_limit_context() :: dmsl_payproc_thrift:'RouteLimitContext'().
|
||||||
|
|
||||||
-spec start(hg_client_api:t()) -> pid().
|
-spec start(hg_client_api:t()) -> pid().
|
||||||
start(ApiClient) ->
|
start(ApiClient) ->
|
||||||
start(start, ApiClient).
|
start(start, ApiClient).
|
||||||
@ -150,6 +153,10 @@ repair(InvoiceID, Changes, Action, Params, Client) ->
|
|||||||
repair_scenario(InvoiceID, Scenario, Client) ->
|
repair_scenario(InvoiceID, Scenario, Client) ->
|
||||||
map_result_error(gen_server:call(Client, {call, 'RepairWithScenario', [InvoiceID, Scenario]})).
|
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()) ->
|
-spec create_invoice_adjustment(invoice_id(), invoice_adjustment_params(), pid()) ->
|
||||||
invoice_adjustment() | woody_error:business_error().
|
invoice_adjustment() | woody_error:business_error().
|
||||||
create_invoice_adjustment(InvoiceID, Params, Client) ->
|
create_invoice_adjustment(InvoiceID, Params, Client) ->
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.11.0">>},2},
|
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.11.0">>},2},
|
||||||
{<<"damsel">>,
|
{<<"damsel">>,
|
||||||
{git,"https://github.com/valitydev/damsel.git",
|
{git,"https://github.com/valitydev/damsel.git",
|
||||||
{ref,"03bf41075c39b6731c5ed200d5c4b0faaee9d937"}},
|
{ref,"52dbefd54fd68d0c04f8ded5734b27635e939c60"}},
|
||||||
0},
|
0},
|
||||||
{<<"dmt_client">>,
|
{<<"dmt_client">>,
|
||||||
{git,"https://github.com/valitydev/dmt-client.git",
|
{git,"https://github.com/valitydev/dmt-client.git",
|
||||||
|
Loading…
Reference in New Issue
Block a user