TD-329: Add withdrawal context support (#12)

* Bump to valitydev/machinery-erlang@62c3243
* Bump to valitydev/machinegun-proto@347c5c4
* Drop top-level `damsel` dependency
* Drop `get_rate` testcase as meaningless
* Drop testcases which became duplicate
* Support new context type @ config
* Delegate context accessors to specific modules
* Support rollbacks @ valitydev/limiter-proto@6158184
This commit is contained in:
Andrew Mayorov 2022-07-06 18:32:32 +03:00 committed by GitHub
parent 2dff7b518d
commit 618a751712
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 819 additions and 1004 deletions

4
.env
View File

@ -1,4 +1,4 @@
SERVICE_NAME=limiter
OTP_VERSION=24.2.0
OTP_VERSION=24.3.4
REBAR_VERSION=3.18
THRIFT_VERSION=0.14.2.2
THRIFT_VERSION=0.14.2.3

View File

@ -161,7 +161,7 @@ call_accounter(Function, Args, LimitContext) ->
WoodyContext = lim_context:woody_context(LimitContext),
lim_client_woody:call(accounter, Function, Args, WoodyContext).
convert_exception(#'InvalidRequest'{errors = Errors}) ->
convert_exception(#base_InvalidRequest{errors = Errors}) ->
Errors;
convert_exception(#accounter_InvalidPostingParams{wrong_postings = Errors}) ->
maps:fold(fun(_, Error, Acc) -> [Error | Acc] end, [], Errors).

View File

@ -8,7 +8,7 @@
currency := currency()
}.
-type currency() :: lim_domain_thrift:'CurrencySymbolicCode'().
-type currency() :: dmsl_domain_thrift:'CurrencySymbolicCode'().
-type config() :: lim_config_machine:config().
-type body_type() :: full | partial.
@ -24,47 +24,18 @@ get(BodyType, Config, LimitContext) ->
do(fun() ->
ContextType = lim_config_machine:context_type(Config),
{ok, Operation} = lim_context:get_operation(ContextType, LimitContext),
Body = unwrap(get_body_for_operation(BodyType, Operation, Config, LimitContext)),
apply_op_behaviour(Body, Config, LimitContext)
Body = unwrap(get_body_for_operation(BodyType, ContextType, LimitContext)),
apply_op_behaviour(Operation, Body, Config)
end).
-spec get_body_for_operation(body_type(), lim_context:context_operation(), config(), lim_context:t()) ->
-spec get_body_for_operation(body_type(), lim_context:context_type(), lim_context:t()) ->
{ok, cash()} | {error, notfound}.
get_body_for_operation(full, invoice = Operation, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
lim_context:get_from_context(ContextType, cost, Operation, LimitContext);
get_body_for_operation(full, invoice_adjustment, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
lim_context:get_from_context(ContextType, cost, invoice, LimitContext);
get_body_for_operation(full, invoice_payment = Operation, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
lim_context:get_from_context(ContextType, cost, Operation, LimitContext);
get_body_for_operation(full, invoice_payment_adjustment, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
lim_context:get_from_context(ContextType, cost, invoice_payment, LimitContext);
get_body_for_operation(full, invoice_payment_refund, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
lim_context:get_from_context(ContextType, cost, invoice_payment, LimitContext);
get_body_for_operation(full, invoice_payment_chargeback = Operation, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
lim_context:get_from_context(ContextType, body, Operation, LimitContext);
get_body_for_operation(partial, invoice, _Config, _LimitContext) ->
{error, notfound};
get_body_for_operation(partial, invoice_adjustment, _Config, _LimitContext) ->
{error, notfound};
get_body_for_operation(partial, invoice_payment = Operation, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
lim_context:get_from_context(ContextType, capture_cost, Operation, LimitContext);
get_body_for_operation(partial, invoice_payment_adjustment, _Config, _LimitContext) ->
{error, notfound};
get_body_for_operation(partial, invoice_payment_refund = Operation, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
lim_context:get_from_context(ContextType, cost, Operation, LimitContext);
get_body_for_operation(partial, invoice_payment_chargeback, _Config, _LimitContext) ->
{error, notfound}.
get_body_for_operation(full, ContextType, LimitContext) ->
lim_context:get_value(ContextType, cost, LimitContext);
get_body_for_operation(partial, ContextType, LimitContext) ->
lim_context:get_value(ContextType, capture_cost, LimitContext).
apply_op_behaviour(Body, #{op_behaviour := ComputationConfig}, LimitContext) ->
{ok, Operation} = lim_context:get_operation(payment_processing, LimitContext),
apply_op_behaviour(Operation, Body, #{op_behaviour := ComputationConfig}) ->
case maps:get(Operation, ComputationConfig, undefined) of
addition ->
Body;
@ -73,7 +44,7 @@ apply_op_behaviour(Body, #{op_behaviour := ComputationConfig}, LimitContext) ->
undefined ->
Body
end;
apply_op_behaviour(Body, _Config, _LimitContext) ->
apply_op_behaviour(_Operation, Body, _Config) ->
Body.
invert_body(Cash = #{amount := Amount}) ->

View File

@ -1,6 +1,7 @@
-module(lim_config_codec).
-include_lib("limiter_proto/include/lim_limiter_config_thrift.hrl").
-include_lib("limiter_proto/include/limproto_config_thrift.hrl").
-include_lib("limiter_proto/include/limproto_timerange_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).
@ -35,7 +36,7 @@ maybe_apply(Value, Fun, _Default) ->
-spec marshal(type_name(), decoded_value()) -> encoded_value().
marshal(timestamped_change, {ev, Timestamp, Change}) ->
#limiter_config_TimestampedChange{
#config_TimestampedChange{
change = marshal_change(Change),
occured_at = marshal_timestamp(Timestamp)
}.
@ -53,11 +54,11 @@ marshal_timestamp({DateTime, USec}) ->
genlib_rfc3339:format_relaxed(TimeinUnit, Unit).
marshal_change({created, Config}) ->
{created, #limiter_config_CreatedChange{limit_config = marshal_config(Config)}}.
{created, #config_CreatedChange{limit_config = marshal_config(Config)}}.
-spec marshal_config(decoded_value()) -> encoded_value().
marshal_config(Config) ->
#limiter_config_LimitConfig{
#config_LimitConfig{
id = lim_config_machine:id(Config),
processor_type = lim_config_machine:processor_type(Config),
description = lim_config_machine:description(Config),
@ -73,62 +74,64 @@ marshal_config(Config) ->
marshal_op_behaviour(OpBehaviour) ->
PaymentRefund = maps:get(invoice_payment_refund, OpBehaviour, undefined),
#limiter_config_OperationLimitBehaviour{
#config_OperationLimitBehaviour{
invoice_payment_refund = maybe_apply(PaymentRefund, fun marshal_behaviour/1)
}.
marshal_behaviour(subtraction) ->
{subtraction, #limiter_config_Subtraction{}};
{subtraction, #config_Subtraction{}};
marshal_behaviour(addition) ->
{addition, #limiter_config_Addition{}}.
{addition, #config_Addition{}}.
marshal_time_range_type({calendar, CalendarType}) ->
{calendar, marshal_calendar_time_range_type(CalendarType)};
marshal_time_range_type({interval, Amount}) ->
{interval, #limiter_time_range_TimeRangeTypeInterval{amount = Amount}}.
{interval, #timerange_TimeRangeTypeInterval{amount = Amount}}.
marshal_calendar_time_range_type(day) ->
{day, #limiter_time_range_TimeRangeTypeCalendarDay{}};
{day, #timerange_TimeRangeTypeCalendarDay{}};
marshal_calendar_time_range_type(week) ->
{week, #limiter_time_range_TimeRangeTypeCalendarWeek{}};
{week, #timerange_TimeRangeTypeCalendarWeek{}};
marshal_calendar_time_range_type(month) ->
{month, #limiter_time_range_TimeRangeTypeCalendarMonth{}};
{month, #timerange_TimeRangeTypeCalendarMonth{}};
marshal_calendar_time_range_type(year) ->
{year, #limiter_time_range_TimeRangeTypeCalendarYear{}}.
{year, #timerange_TimeRangeTypeCalendarYear{}}.
marshal_context_type(payment_processing) ->
{payment_processing, #limiter_config_LimitContextTypePaymentProcessing{}}.
{payment_processing, #config_LimitContextTypePaymentProcessing{}};
marshal_context_type(withdrawal_processing) ->
{withdrawal_processing, #config_LimitContextTypeWithdrawalProcessing{}}.
marshal_type({turnover, Metric}) ->
{turnover, #limiter_config_LimitTypeTurnover{
{turnover, #config_LimitTypeTurnover{
metric = marshal_turnover_metric(Metric)
}}.
marshal_turnover_metric(number) ->
{number, #limiter_config_LimitTurnoverNumber{}};
{number, #config_LimitTurnoverNumber{}};
marshal_turnover_metric({amount, Currency}) ->
{amount, #limiter_config_LimitTurnoverAmount{currency = Currency}}.
{amount, #config_LimitTurnoverAmount{currency = Currency}}.
marshal_scope(Types) ->
{multi, ordsets:from_list(lists:map(fun marshal_scope_type/1, ordsets:to_list(Types)))}.
marshal_scope_type(party) ->
{party, #limiter_config_LimitScopeEmptyDetails{}};
{party, #config_LimitScopeEmptyDetails{}};
marshal_scope_type(shop) ->
{shop, #limiter_config_LimitScopeEmptyDetails{}};
{shop, #config_LimitScopeEmptyDetails{}};
marshal_scope_type(wallet) ->
{wallet, #limiter_config_LimitScopeEmptyDetails{}};
{wallet, #config_LimitScopeEmptyDetails{}};
marshal_scope_type(identity) ->
{identity, #limiter_config_LimitScopeEmptyDetails{}};
{identity, #config_LimitScopeEmptyDetails{}};
marshal_scope_type(payment_tool) ->
{payment_tool, #limiter_config_LimitScopeEmptyDetails{}}.
{payment_tool, #config_LimitScopeEmptyDetails{}}.
%%
-spec unmarshal(type_name(), encoded_value()) -> decoded_value().
unmarshal(timestamped_change, TimestampedChange) ->
Timestamp = unmarshal_timestamp(TimestampedChange#limiter_config_TimestampedChange.occured_at),
Change = unmarshal_change(TimestampedChange#limiter_config_TimestampedChange.change),
Timestamp = unmarshal_timestamp(TimestampedChange#config_TimestampedChange.occured_at),
Change = unmarshal_change(TimestampedChange#config_TimestampedChange.change),
{ev, Timestamp, Change}.
unmarshal_timestamp(Timestamp) when is_binary(Timestamp) ->
@ -148,7 +151,7 @@ unmarshal_timestamp(Timestamp) when is_binary(Timestamp) ->
end.
-spec unmarshal_params(encoded_value()) -> decoded_value().
unmarshal_params(#limiter_config_LimitConfigParams{
unmarshal_params(#config_LimitConfigParams{
id = ID,
description = Description,
started_at = StartedAt,
@ -171,10 +174,10 @@ unmarshal_params(#limiter_config_LimitConfigParams{
op_behaviour => maybe_apply(OpBehaviour, fun unmarshal_op_behaviour/1)
}).
unmarshal_change({created, #limiter_config_CreatedChange{limit_config = Config}}) ->
unmarshal_change({created, #config_CreatedChange{limit_config = Config}}) ->
{created, unmarshal_config(Config)}.
unmarshal_config(#limiter_config_LimitConfig{
unmarshal_config(#config_LimitConfig{
id = ID,
processor_type = ProcessorType,
description = Description,
@ -217,25 +220,25 @@ derive_type(undefined, {cash, Currency}) ->
-spec unmarshal_op_behaviour(encoded_value()) -> decoded_value().
unmarshal_op_behaviour(OpBehaviour) ->
#limiter_config_OperationLimitBehaviour{
#config_OperationLimitBehaviour{
invoice_payment_refund = Refund
} = OpBehaviour,
genlib_map:compact(#{
invoice_payment_refund => maybe_apply(Refund, fun unmarshal_behaviour/1)
}).
unmarshal_behaviour({subtraction, #limiter_config_Subtraction{}}) ->
unmarshal_behaviour({subtraction, #config_Subtraction{}}) ->
subtraction;
unmarshal_behaviour({addition, #limiter_config_Addition{}}) ->
unmarshal_behaviour({addition, #config_Addition{}}) ->
addition.
-spec unmarshal_body_type_deprecated(encoded_value()) -> decoded_value().
unmarshal_body_type_deprecated({cash, #limiter_config_LimitBodyTypeCash{currency = Currency}}) ->
unmarshal_body_type_deprecated({cash, #config_LimitBodyTypeCash{currency = Currency}}) ->
{cash, Currency}.
unmarshal_time_range_type({calendar, CalendarType}) ->
{calendar, unmarshal_calendar_time_range_type(CalendarType)};
unmarshal_time_range_type({interval, #limiter_time_range_TimeRangeTypeInterval{amount = Amount}}) ->
unmarshal_time_range_type({interval, #timerange_TimeRangeTypeInterval{amount = Amount}}) ->
{interval, Amount}.
unmarshal_calendar_time_range_type({day, _}) ->
@ -247,15 +250,17 @@ unmarshal_calendar_time_range_type({month, _}) ->
unmarshal_calendar_time_range_type({year, _}) ->
year.
unmarshal_context_type({payment_processing, #limiter_config_LimitContextTypePaymentProcessing{}}) ->
payment_processing.
unmarshal_context_type({payment_processing, #config_LimitContextTypePaymentProcessing{}}) ->
payment_processing;
unmarshal_context_type({withdrawal_processing, #config_LimitContextTypeWithdrawalProcessing{}}) ->
withdrawal_processing.
unmarshal_type({turnover, #limiter_config_LimitTypeTurnover{metric = Metric}}) ->
unmarshal_type({turnover, #config_LimitTypeTurnover{metric = Metric}}) ->
{turnover, maybe_apply(Metric, fun unmarshal_turnover_metric/1, number)}.
unmarshal_turnover_metric({number, _}) ->
number;
unmarshal_turnover_metric({amount, #limiter_config_LimitTurnoverAmount{currency = Currency}}) ->
unmarshal_turnover_metric({amount, #config_LimitTurnoverAmount{currency = Currency}}) ->
{amount, Currency}.
unmarshal_scope({single, Type}) ->
@ -302,15 +307,15 @@ marshal_unmarshal_created_test() ->
-spec unmarshal_created_w_deprecated_body_type_test_() -> [_TestGen].
unmarshal_created_w_deprecated_body_type_test_() ->
Now = lim_time:now(),
Config = #limiter_config_LimitConfig{
Config = #config_LimitConfig{
id = <<"ID">>,
processor_type = <<"TurnoverProcessor">>,
created_at = lim_time:to_rfc3339(Now),
started_at = <<"2000-01-01T00:00:00Z">>,
shard_size = 42,
time_range_type = {calendar, {day, #limiter_time_range_TimeRangeTypeCalendarDay{}}},
context_type = {payment_processing, #limiter_config_LimitContextTypePaymentProcessing{}},
body_type_deprecated = {cash, #limiter_config_LimitBodyTypeCash{currency = <<"☭☭☭"/utf8>>}}
time_range_type = {calendar, {day, #timerange_TimeRangeTypeCalendarDay{}}},
context_type = {payment_processing, #config_LimitContextTypePaymentProcessing{}},
body_type_deprecated = {cash, #config_LimitBodyTypeCash{currency = <<"☭☭☭"/utf8>>}}
},
[
?_assertMatch(
@ -320,8 +325,8 @@ unmarshal_created_w_deprecated_body_type_test_() ->
type := {turnover, {amount, <<"☭☭☭"/utf8>>}}
}},
unmarshal_change(
{created, #limiter_config_CreatedChange{
limit_config = Config#limiter_config_LimitConfig{
{created, #config_CreatedChange{
limit_config = Config#config_LimitConfig{
type = undefined
}
}}
@ -334,9 +339,9 @@ unmarshal_created_w_deprecated_body_type_test_() ->
type := {turnover, {amount, <<"☭☭☭"/utf8>>}}
}},
unmarshal_change(
{created, #limiter_config_CreatedChange{
limit_config = Config#limiter_config_LimitConfig{
type = {turnover, #limiter_config_LimitTypeTurnover{}}
{created, #config_CreatedChange{
limit_config = Config#config_LimitConfig{
type = {turnover, #config_LimitTypeTurnover{}}
}
}}
)

View File

@ -1,6 +1,6 @@
-module(lim_config_machine).
-include_lib("limiter_proto/include/lim_limiter_thrift.hrl").
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
%% Accessors
@ -79,10 +79,10 @@
-type op_behaviour() :: #{operation_type() := addition | subtraction}.
-type operation_type() :: invoice_payment_refund.
-type lim_id() :: lim_limiter_thrift:'LimitID'().
-type lim_change() :: lim_limiter_thrift:'LimitChange'().
-type limit() :: lim_limiter_thrift:'Limit'().
-type timestamp() :: lim_base_thrift:'Timestamp'().
-type lim_id() :: limproto_limiter_thrift:'LimitID'().
-type lim_change() :: limproto_limiter_thrift:'LimitChange'().
-type limit() :: limproto_limiter_thrift:'Limit'().
-type timestamp() :: dmsl_base_thrift:'Timestamp'().
-export_type([config/0]).
-export_type([limit_type/0]).
@ -522,14 +522,14 @@ mk_shard_id(Prefix, Units, ShardSize) ->
-spec mk_scope_prefix(config(), lim_context()) -> prefix().
mk_scope_prefix(Config, LimitContext) ->
mk_scope_prefix_impl(scope(Config), LimitContext).
mk_scope_prefix_impl(scope(Config), context_type(Config), LimitContext).
-spec mk_scope_prefix_impl(limit_scope(), lim_context()) -> prefix().
mk_scope_prefix_impl(Scope, LimitContext) ->
-spec mk_scope_prefix_impl(limit_scope(), context_type(), lim_context()) -> prefix().
mk_scope_prefix_impl(Scope, ContextType, LimitContext) ->
Bits = enumerate_context_bits(Scope),
ordsets:fold(
fun(Bit, Acc) ->
{ok, Value} = extract_context_bit(Bit, LimitContext),
{ok, Value} = extract_context_bit(Bit, ContextType, LimitContext),
append_prefix(Value, Acc)
end,
<<>>,
@ -541,7 +541,7 @@ append_prefix(Fragment, Acc) ->
<<Acc/binary, "/", Fragment/binary>>.
-type context_bit() ::
{from, lim_context:context_type(), _Name :: atom(), lim_context:context_operation()}
{from, _ValueName :: atom()}
| {order, integer(), context_bit()}.
-spec enumerate_context_bits(limit_scope()) -> ordsets:ordset(context_bit()).
@ -550,7 +550,7 @@ enumerate_context_bits(Types) ->
append_context_bits(party, Bits) ->
ordsets:add_element(
{order, 1, {from, payment_processing, owner_id, invoice}},
{order, 1, {from, owner_id}},
Bits
);
append_context_bits(shop, Bits) ->
@ -558,31 +558,33 @@ append_context_bits(shop, Bits) ->
% NOTE
% Shop scope implies party scope.
% Also we need to preserve order between party / shop to ensure backwards compatibility.
{order, 1, {from, payment_processing, owner_id, invoice}},
{order, 2, {from, payment_processing, shop_id, invoice}}
{order, 1, {from, owner_id}},
{order, 2, {from, shop_id}}
]);
append_context_bits(payment_tool, Bits) ->
ordsets:add_element(
{from, payment_processing, payer, invoice_payment},
{from, payment_tool},
Bits
).
-spec extract_context_bit(context_bit(), lim_context()) -> {ok, binary()}.
extract_context_bit({order, _, Bit}, LimitContext) ->
extract_context_bit(Bit, LimitContext);
extract_context_bit({from, payment_processing, payer, Op}, LimitContext) ->
{ok, {_, PayerData}} = lim_context:get_from_context(payment_processing, payer, Op, LimitContext),
#{payment_tool := {PaymentToolType, PaymentToolData}} = PayerData,
case PaymentToolType of
bank_card ->
Token = maps:get(token, PaymentToolData),
ExpData = maps:get(exp_date, PaymentToolData, <<>>),
{ok, <<Token/binary, "/", ExpData/binary>>};
_ ->
{error, {unsupported_payment_tool_type, PaymentToolType}}
-spec extract_context_bit(context_bit(), context_type(), lim_context()) -> {ok, binary()}.
extract_context_bit({order, _, Bit}, ContextType, LimitContext) ->
extract_context_bit(Bit, ContextType, LimitContext);
extract_context_bit({from, payment_tool}, ContextType, LimitContext) ->
{ok, PaymentTool} = lim_context:get_value(ContextType, payment_tool, LimitContext),
case PaymentTool of
{bank_card, #{token := Token, exp_date := {Month, Year}}} ->
{ok, mk_scope_component([Token, Month, Year])};
{bank_card, #{token := Token, exp_date := undefined}} ->
{ok, mk_scope_component([Token, <<"undefined">>])};
{digital_wallet, #{id := ID, service := Service}} ->
{ok, mk_scope_component([<<"DW">>, Service, ID])}
end;
extract_context_bit({from, ContextType, ValueName, Op}, LimitContext) ->
lim_context:get_from_context(ContextType, ValueName, Op, LimitContext).
extract_context_bit({from, ValueName}, ContextType, LimitContext) ->
lim_context:get_value(ContextType, ValueName, LimitContext).
mk_scope_component(Fragments) ->
lim_string:join($/, Fragments).
%%% Machinery callbacks
@ -640,6 +642,9 @@ apply_event_({created, Config}, undefined) ->
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-include_lib("limiter_proto/include/limproto_context_payproc_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-spec test() -> _.
-spec check_sign_prefix_test() -> _.
@ -782,32 +787,42 @@ check_calculate_year_shard_id_test() ->
?assertEqual(<<"past/year/1">>, calculate_calendar_shard_id(year, <<"2000-01-01T00:00:00Z">>, StartedAt2, 1)),
?assertEqual(<<"future/year/0">>, calculate_calendar_shard_id(year, <<"2001-01-01T00:00:00Z">>, StartedAt2, 1)).
-define(LIMIT_CONTEXT, #{
context => #{
payment_processing => #{
op => invoice,
invoice => #{
owner_id => <<"OWNER">>,
shop_id => <<"SHLOP">>
}
-define(PAYPROC_CTX_INVOICE(Invoice), #limiter_LimitContext{
payment_processing = #context_payproc_Context{
op = {invoice, #context_payproc_OperationInvoice{}},
invoice = #context_payproc_Invoice{
invoice = Invoice
}
}
}).
-define(INVOICE(OwnerID, ShopID), #domain_Invoice{
id = <<"ID">>,
owner_id = OwnerID,
shop_id = ShopID,
created_at = <<"2000-02-02T12:12:12Z">>,
status = {unpaid, #domain_InvoiceUnpaid{}},
details = #domain_InvoiceDetails{product = <<>>},
due = <<"2222-02-02T12:12:12Z">>,
cost = #domain_Cash{amount = 42, currency = #domain_CurrencyRef{symbolic_code = <<"CNY">>}}
}).
-spec global_scope_empty_prefix_test() -> _.
global_scope_empty_prefix_test() ->
?assertEqual(<<>>, mk_scope_prefix_impl(ordsets:new(), ?LIMIT_CONTEXT)).
Context = #{context => ?PAYPROC_CTX_INVOICE(?INVOICE(<<"OWNER">>, <<"SHOP">>))},
?assertEqual(<<>>, mk_scope_prefix_impl(ordsets:new(), payment_processing, Context)).
-spec preserve_scope_prefix_order_test_() -> [_TestGen].
preserve_scope_prefix_order_test_() ->
Context = #{context => ?PAYPROC_CTX_INVOICE(?INVOICE(<<"OWNER">>, <<"SHLOP">>))},
[
?_assertEqual(
<<"/OWNER/SHLOP">>,
mk_scope_prefix_impl(ordsets:from_list([shop, party]), ?LIMIT_CONTEXT)
mk_scope_prefix_impl(ordsets:from_list([shop, party]), payment_processing, Context)
),
?_assertEqual(
<<"/OWNER/SHLOP">>,
mk_scope_prefix_impl(ordsets:from_list([shop]), ?LIMIT_CONTEXT)
mk_scope_prefix_impl(ordsets:from_list([shop]), payment_processing, Context)
)
].

View File

@ -70,13 +70,13 @@ unmarshal(T, V, C) when
-spec marshal_event(machinery_mg_schema:version(), event(), context()) -> {machinery_msgpack:t(), context()}.
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = lim_config_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {lim_limiter_config_thrift, 'TimestampedChange'}},
Type = {struct, struct, {limproto_config_thrift, 'TimestampedChange'}},
{{bin, lim_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {lim_limiter_config_thrift, 'TimestampedChange'}},
Type = {struct, struct, {limproto_config_thrift, 'TimestampedChange'}},
ThriftChange = lim_proto_utils:deserialize(Type, EncodedThriftChange),
{lim_config_codec:unmarshal(timestamped_change, ThriftChange), Context}.
@ -104,7 +104,7 @@ marshal_unmarshal_created_test() ->
scope => ordsets:from_list([party]),
description => <<"description">>
}},
Context = #{machine_ref => ID, machine_ns => config},
Context = #{machine_id => ID, machine_ns => config},
Event = {ev, lim_time:machinery_now(), Created},
{Marshaled, _} = marshal_event(1, Event, Context),
{Unmarshaled, _} = unmarshal_event(1, Marshaled, Context),

View File

@ -1,6 +1,7 @@
-module(lim_configurator).
-include_lib("limiter_proto/include/lim_configurator_thrift.hrl").
-include_lib("limiter_proto/include/limproto_configurator_thrift.hrl").
-include_lib("damsel/include/dmsl_base_thrift.hrl").
%% Woody handler
@ -23,7 +24,7 @@ handle_function(Fn, Args, WoodyCtx, Opts) ->
-spec handle_function_(woody:func(), woody:args(), lim_context:t(), woody:options()) -> {ok, woody:result()}.
handle_function_(
'CreateLegacy',
{#limiter_configurator_LimitCreateParams{
{#configurator_LimitCreateParams{
id = ID,
name = Name,
description = Description,
@ -51,7 +52,7 @@ handle_function_(
{error, {name, notfound}} ->
woody_error:raise(
business,
#limiter_configurator_LimitConfigNameNotFound{}
#configurator_LimitConfigNameNotFound{}
)
end;
handle_function_('Create', {Params}, LimitContext, _Opts) ->
@ -70,7 +71,7 @@ handle_function_('Get', {LimitID}, LimitContext, _Opts) ->
{ok, LimitConfig} ->
{ok, lim_config_codec:marshal_config(LimitConfig)};
{error, notfound} ->
woody_error:raise(business, #limiter_configurator_LimitConfigNotFound{})
woody_error:raise(business, #configurator_LimitConfigNotFound{})
end.
map_type({turnover, _}) ->
@ -78,7 +79,7 @@ map_type({turnover, _}) ->
map_type(_) ->
woody_error:raise(
business,
#'InvalidRequest'{errors = [<<"Config type not found.">>]}
#base_InvalidRequest{errors = [<<"Config type not found.">>]}
).
mk_limit_config(<<"ShopDayTurnover">>) ->

View File

@ -1,12 +1,11 @@
-module(lim_context).
-include_lib("limiter_proto/include/lim_limiter_context_thrift.hrl").
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
-export([create/1]).
-export([woody_context/1]).
-export([get_operation/2]).
-export([get_from_context/3]).
-export([get_from_context/4]).
-export([get_value/3]).
-export([set_context/2]).
-export([set_clock/2]).
@ -14,107 +13,26 @@
-export([clock/1]).
-type woody_context() :: woody_context:ctx().
-type timestamp() :: binary().
-type thrift_context() :: lim_limiter_thrift:'LimitContext'().
-type clock() :: lim_limiter_thrift:'Clock'().
-type id() :: binary().
-type token() :: binary().
-type exp_date() :: binary().
-type cash() :: lim_body:cash().
-type limit_context() :: limproto_limiter_thrift:'LimitContext'().
-type clock() :: limproto_limiter_thrift:'Clock'().
-type t() :: #{
woody_context => woody_context(),
context => context(),
context => limit_context(),
clock => clock()
}.
-type context_type() :: payment_processing.
-type context_operation() :: payment_processing_operation().
-type context() :: #{
payment_processing => payment_processing_context()
}.
-type payment_processing_context() :: #{
op := payment_processing_operation(),
invoice => payment_processing_invoice()
}.
-type payment_processing_operation() ::
invoice
| invoice_adjustment
| invoice_payment
| invoice_payment_adjustment
| invoice_payment_refund
| invoice_payment_chargeback.
-type payment_processing_invoice() :: #{
id => id(),
owner_id => id(),
shop_id => id(),
cost => cash(),
created_at => timestamp(),
adjustment => payment_processing_adjustment(),
payment => payment_processing_payment()
}.
-type payment_processing_adjustment() :: #{
id => id()
}.
-type payment_processing_payment() :: #{
id => id(),
owner_id => id(),
shop_id => id(),
cost => cash(),
capture_cost => cash(),
created_at => timestamp(),
flow => instant | hold,
payer => payment_processing_payer(),
adjustment => payment_processing_payment_adjustment(),
refund => payment_processing_payment_refund(),
chargeback => payment_processing_payment_chargeback()
}.
-type payment_processing_payer() ::
{payment_resource, payment_processing_payer_data()}
| {customer, payment_processing_payer_data()}
| {recurrent, payment_processing_payer_data()}.
-type payment_processing_payer_data() :: #{
payment_tool => payment_processing_payment_tool()
}.
-type payment_processing_payment_tool() :: {bank_card, payment_processing_bank_card()}.
-type payment_processing_bank_card() :: #{
token => token(),
exp_date => exp_date()
}.
-type payment_processing_payment_adjustment() :: #{
id => id(),
created_at => timestamp()
}.
-type payment_processing_payment_refund() :: #{
id => id(),
cost => cash(),
created_at => timestamp()
}.
-type payment_processing_payment_chargeback() :: #{
id => id(),
levy => cash(),
body => cash(),
created_at => timestamp()
}.
-type context_type() :: payment_processing | withdrawal_processing.
-type context_inner() :: lim_payproc_context:context() | lim_wthdproc_context:context().
-type context_operation() :: lim_payproc_context:operation() | lim_wthdproc_context:operation().
-export_type([t/0]).
-export_type([context/0]).
-export_type([context_type/0]).
-export_type([context_operation/0]).
-callback get_operation(context_inner()) -> {ok, context_operation()} | {error, notfound}.
-callback get_value(_Name :: atom(), context_inner()) -> {ok, term()} | {error, notfound | {unsupported, _}}.
-spec create(woody_context()) -> t().
create(WoodyContext) ->
#{woody_context => WoodyContext}.
@ -129,83 +47,33 @@ clock(#{clock := Clock}) ->
clock(_) ->
{error, notfound}.
-spec set_context(thrift_context(), t()) -> t().
-spec set_context(limit_context(), t()) -> t().
set_context(Context, LimContext) ->
LimContext#{context => unmarshal_context(Context)}.
LimContext#{context => Context}.
-spec set_clock(clock(), t()) -> t().
set_clock(Clock, LimContext) ->
LimContext#{clock => Clock}.
-spec get_operation(context_type(), t()) -> {ok, atom()} | {error, notfound}.
get_operation(Type, #{context := Context}) ->
case maps:get(Type, Context, undefined) of
undefined ->
{error, notfound};
#{op := Operation} ->
{ok, Operation}
end.
-spec get_operation(context_type(), t()) ->
{ok, context_operation()} | {error, notfound}.
get_operation(Type, Context) ->
{Mod, OperationContext} = get_operation_context(Type, Context),
Mod:get_operation(OperationContext).
-spec get_from_context(context_type(), atom(), t()) -> {ok, term()} | {error, notfound}.
get_from_context(payment_processing, ValueName, LimContext = #{context := Context}) ->
case maps:get(payment_processing, Context, undefined) of
undefined ->
{error, notfound};
#{op := Operation} ->
get_from_context(payment_processing, ValueName, Operation, LimContext)
end;
get_from_context(_, _ValueName, _LimContext) ->
{error, notfound}.
-spec get_value(context_type(), atom(), t()) ->
{ok, term()} | {error, notfound | {unsupported, _}}.
get_value(Type, ValueName, Context) ->
{Mod, OperationContext} = get_operation_context(Type, Context),
Mod:get_value(ValueName, OperationContext).
-spec get_from_context(context_type(), atom(), context_operation(), t()) -> {ok, term()} | {error, notfound}.
get_from_context(payment_processing, ValueName, Op, #{context := #{payment_processing := Context}}) ->
case get_payment_processing_operation_context(Op, Context) of
{ok, OperationContext} ->
case maps:get(ValueName, OperationContext, undefined) of
undefined ->
{error, notfound};
Value ->
{ok, Value}
end;
Error ->
Error
end;
get_from_context(_, _ValueName, _Op, _LimContext) ->
{error, notfound}.
get_payment_processing_operation_context(invoice, #{invoice := Invoice}) ->
{ok, Invoice};
get_payment_processing_operation_context(invoice_adjustment, #{invoice := #{adjustment := Adjustment}}) ->
{ok, Adjustment};
get_payment_processing_operation_context(invoice_payment, #{invoice := #{payment := Payment}}) ->
{ok, Payment};
get_payment_processing_operation_context(
invoice_payment_adjustment,
#{invoice := #{payment := #{adjustment := Adjustment}}}
get_operation_context(
payment_processing,
#{context := #limiter_LimitContext{payment_processing = PayprocContext}}
) ->
{ok, Adjustment};
get_payment_processing_operation_context(
invoice_payment_refund,
#{invoice := #{payment := #{refund := Refund}}}
{lim_payproc_context, PayprocContext};
get_operation_context(
withdrawal_processing,
#{context := #limiter_LimitContext{withdrawal_processing = WithdrawalContext}}
) ->
{ok, Refund};
get_payment_processing_operation_context(
invoice_payment_chargeback,
#{invoice := #{payment := #{chargeback := Chargeback}}}
) ->
{ok, Chargeback};
get_payment_processing_operation_context(_, _) ->
{error, notfound}.
%%
unmarshal_context(#limiter_context_LimitContext{limiter_payment_processing = PaymentProcessing}) when
PaymentProcessing =/= undefined
->
#{payment_processing => lim_limiter_context:unmarshal(PaymentProcessing)};
unmarshal_context(#limiter_context_LimitContext{payment_processing = PaymentProcessing}) when
PaymentProcessing =/= undefined
->
#{payment_processing => lim_payproc_context:unmarshal(PaymentProcessing)};
unmarshal_context(_) ->
#{}.
{lim_wthdproc_context, WithdrawalContext}.

View File

@ -1,6 +1,8 @@
-module(lim_handler).
-include_lib("limiter_proto/include/lim_limiter_thrift.hrl").
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
-include_lib("limiter_proto/include/limproto_base_thrift.hrl").
-include_lib("damsel/include/dmsl_base_thrift.hrl").
%% Woody handler
@ -84,7 +86,7 @@ handle_get_error(Error) ->
-spec handle_hold_error(_) -> no_return().
handle_hold_error({_, {invalid_request, Errors}}) ->
woody_error:raise(business, #'InvalidRequest'{errors = Errors});
woody_error:raise(business, #base_InvalidRequest{errors = Errors});
handle_hold_error(Error) ->
handle_default_error(Error).
@ -92,13 +94,13 @@ handle_hold_error(Error) ->
handle_commit_error({_, {forbidden_operation_amount, Error}}) ->
handle_forbidden_operation_amount_error(Error);
handle_commit_error({_, {invalid_request, Errors}}) ->
woody_error:raise(business, #'InvalidRequest'{errors = Errors});
woody_error:raise(business, #base_InvalidRequest{errors = Errors});
handle_commit_error(Error) ->
handle_default_error(Error).
-spec handle_rollback_error(_) -> no_return().
handle_rollback_error({_, {invalid_request, Errors}}) ->
woody_error:raise(business, #'InvalidRequest'{errors = Errors});
woody_error:raise(business, #base_InvalidRequest{errors = Errors});
handle_rollback_error(Error) ->
handle_default_error(Error).
@ -122,7 +124,7 @@ handle_forbidden_operation_amount_error(#{
positive ->
woody_error:raise(business, #limiter_ForbiddenOperationAmount{
amount = Partial,
allowed_range = #limiter_base_AmountRange{
allowed_range = #base_AmountRange{
upper = {inclusive, Full},
lower = {inclusive, 0}
}
@ -130,7 +132,7 @@ handle_forbidden_operation_amount_error(#{
negative ->
woody_error:raise(business, #limiter_ForbiddenOperationAmount{
amount = Partial,
allowed_range = #limiter_base_AmountRange{
allowed_range = #base_AmountRange{
upper = {inclusive, 0},
lower = {inclusive, Full}
}

View File

@ -1,129 +0,0 @@
-module(lim_limiter_context).
-include_lib("limiter_proto/include/lim_limiter_context_thrift.hrl").
-export([unmarshal/1]).
-type thrift_context() :: lim_limiter_context_thrift:'ContextPaymentProcessing'().
%%
-spec unmarshal(thrift_context()) -> lim_context:context().
unmarshal(#limiter_context_ContextPaymentProcessing{
op = {Operation, _},
invoice = Invoice
}) ->
genlib_map:compact(#{
op => Operation,
invoice => maybe_unmarshal(Invoice, fun unmarshal_payment_processing_invoice/1)
}).
unmarshal_payment_processing_invoice(#limiter_context_Invoice{
id = ID,
owner_id = OwnerID,
shop_id = ShopID,
cost = Cost,
created_at = CreatedAt,
effective_payment = Payment,
effective_adjustment = Adjustment
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
owner_id => maybe_unmarshal(OwnerID, fun unmarshal_string/1),
shop_id => maybe_unmarshal(ShopID, fun unmarshal_string/1),
cost => maybe_unmarshal(Cost, fun unmarshal_cash/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1),
adjustment => maybe_unmarshal(
Adjustment,
fun unmarshal_payment_processing_invoice_adjustment/1
),
payment => maybe_unmarshal(Payment, fun unmarshal_payment_processing_invoice_payment/1)
}).
unmarshal_payment_processing_invoice_adjustment(#limiter_context_InvoiceAdjustment{id = ID}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1)
}).
unmarshal_payment_processing_invoice_payment(#limiter_context_InvoicePayment{
id = ID,
owner_id = OwnerID,
shop_id = ShopID,
cost = Cost,
capture_cost = CaptureCost,
created_at = CreatedAt,
flow = Flow,
payer = Payer,
effective_adjustment = Adjustment,
effective_refund = EffectiveRefund,
effective_chargeback = EffectiveChargeback
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
owner_id => maybe_unmarshal(OwnerID, fun unmarshal_string/1),
shop_id => maybe_unmarshal(ShopID, fun unmarshal_string/1),
cost => maybe_unmarshal(Cost, fun unmarshal_cash/1),
capture_cost => maybe_unmarshal(CaptureCost, fun unmarshal_cash/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1),
flow => maybe_unmarshal(Flow, fun unmarshal_payment_processing_invoice_payment_flow/1),
payer => maybe_unmarshal(Payer, fun unmarshal_payment_processing_invoice_payment_payer/1),
adjustment => maybe_unmarshal(
Adjustment,
fun unmarshal_payment_processing_invoice_payment_adjustment/1
),
refund => maybe_unmarshal(EffectiveRefund, fun unmarshal_payment_processing_invoice_payment_refund/1),
chargeback => maybe_unmarshal(
EffectiveChargeback,
fun unmarshal_payment_processing_invoice_payment_chargeback/1
)
}).
unmarshal_payment_processing_invoice_payment_flow({Flow, _}) ->
Flow.
unmarshal_payment_processing_invoice_payment_payer({Payer, _}) ->
{Payer, #{}}.
unmarshal_payment_processing_invoice_payment_adjustment(#limiter_context_InvoicePaymentAdjustment{
id = ID,
created_at = CreatedAt
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1)
}).
unmarshal_payment_processing_invoice_payment_refund(#limiter_context_InvoicePaymentRefund{
id = ID,
cost = Cost,
created_at = CreatedAt
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
cost => maybe_unmarshal(Cost, fun unmarshal_cash/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1)
}).
unmarshal_payment_processing_invoice_payment_chargeback(#limiter_context_InvoicePaymentChargeback{
id = ID,
levy = Levy,
body = Body,
created_at = CreatedAt
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
levy => maybe_unmarshal(Levy, fun unmarshal_cash/1),
body => maybe_unmarshal(Body, fun unmarshal_cash/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1)
}).
unmarshal_cash(#domain_Cash{amount = Amount, currency = #domain_CurrencyRef{symbolic_code = Currency}}) ->
#{amount => Amount, currency => Currency}.
unmarshal_string(Value) ->
Value.
maybe_unmarshal(undefined, _) ->
undefined;
maybe_unmarshal(Value, UnmarshalFun) ->
UnmarshalFun(Value).

View File

@ -1,213 +1,247 @@
-module(lim_payproc_context).
-include_lib("limiter_proto/include/lim_limiter_payproc_context_thrift.hrl").
-include_lib("limiter_proto/include/limproto_context_payproc_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-export([unmarshal/1]).
-behaviour(lim_context).
-export([get_operation/1]).
-export([get_value/2]).
-type thrift_context() :: lim_limiter_payproc_context_thrift:'Context'().
-type context() :: limproto_context_payproc_thrift:'Context'().
-type operation() ::
invoice
| invoice_adjustment
| invoice_payment
| invoice_payment_adjustment
| invoice_payment_refund
| invoice_payment_chargeback.
-export_type([operation/0]).
-export_type([context/0]).
%%
-spec unmarshal(thrift_context()) -> lim_context:context().
unmarshal(#limiter_context_payproc_Context{
op = {Operation, _},
invoice = Invoice
}) ->
genlib_map:compact(#{
op => Operation,
invoice => maybe_unmarshal(Invoice, fun unmarshal_payment_processing_invoice/1)
-spec get_operation(context()) -> {ok, operation()} | {error, notfound}.
get_operation(#context_payproc_Context{op = {Operation, _}}) ->
{ok, Operation};
get_operation(#context_payproc_Context{op = undefined}) ->
{error, notfound}.
-spec get_value(atom(), context()) -> {ok, term()} | {error, notfound | {unsupported, _}}.
get_value(ValueName, Context) ->
case get_operation(Context) of
{ok, Operation} ->
get_value(ValueName, Operation, Context);
{error, _} = Error ->
Error
end.
get_value(owner_id, _Operation, Context) ->
get_owner_id(Context);
get_value(shop_id, _Operation, Context) ->
get_shop_id(Context);
get_value(created_at, Operation, Context) ->
get_created_at(Operation, Context);
get_value(cost, Operation, Context) ->
get_cost(Operation, Context);
get_value(capture_cost, Operation, Context) ->
get_capture_cost(Operation, Context);
get_value(payment_tool, Operation, Context) ->
get_payment_tool(Operation, Context);
get_value(ValueName, _Operation, _Context) ->
{error, {unsupported, ValueName}}.
%%
-define(INVOICE(V), #context_payproc_Context{
invoice = #context_payproc_Invoice{
invoice = V = #domain_Invoice{}
}
}).
unmarshal_payment_processing_invoice(#limiter_context_payproc_Invoice{
invoice = #domain_Invoice{
id = ID,
owner_id = OwnerID,
shop_id = ShopID,
cost = Cost,
created_at = CreatedAt
},
payment = Payment,
adjustment = Adjustment
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
owner_id => maybe_unmarshal(OwnerID, fun unmarshal_string/1),
shop_id => maybe_unmarshal(ShopID, fun unmarshal_string/1),
cost => maybe_unmarshal(Cost, fun unmarshal_cash/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1),
adjustment => maybe_unmarshal(
Adjustment,
fun unmarshal_payment_processing_invoice_adjustment/1
),
payment => maybe_unmarshal(Payment, fun unmarshal_payment_processing_invoice_payment/1)
-define(INVOICE_ADJUSTMENT(V), #context_payproc_Context{
invoice = #context_payproc_Invoice{
adjustment = V = #domain_InvoiceAdjustment{}
}
}).
unmarshal_payment_processing_invoice_adjustment(#domain_InvoiceAdjustment{id = ID}) ->
#{id => unmarshal_string(ID)}.
unmarshal_payment_processing_invoice_payment(#limiter_context_payproc_InvoicePayment{
payment = #domain_InvoicePayment{
id = ID,
owner_id = OwnerID,
shop_id = ShopID,
cost = Cost,
created_at = CreatedAt,
flow = Flow,
status = Status,
payer = Payer
},
adjustment = Adjustment,
refund = EffectiveRefund,
chargeback = EffectiveChargeback
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
owner_id => maybe_unmarshal(OwnerID, fun unmarshal_string/1),
shop_id => maybe_unmarshal(ShopID, fun unmarshal_string/1),
cost => maybe_unmarshal(Cost, fun unmarshal_cash/1),
capture_cost => get_capture_cost_from_status(Status),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1),
flow => maybe_unmarshal(Flow, fun unmarshal_payment_processing_invoice_payment_flow/1),
payer => maybe_unmarshal(Payer, fun unmarshal_payment_processing_invoice_payment_payer/1),
adjustment => maybe_unmarshal(
Adjustment,
fun unmarshal_payment_processing_invoice_payment_adjustment/1
),
refund => maybe_unmarshal(EffectiveRefund, fun unmarshal_payment_processing_invoice_payment_refund/1),
chargeback => maybe_unmarshal(
EffectiveChargeback,
fun unmarshal_payment_processing_invoice_payment_chargeback/1
)
-define(INVOICE_PAYMENT(V), #context_payproc_Context{
invoice = #context_payproc_Invoice{
payment = #context_payproc_InvoicePayment{payment = V = #domain_InvoicePayment{}}
}
}).
get_capture_cost_from_status({captured, #domain_InvoicePaymentCaptured{cost = Cost}}) ->
maybe_unmarshal(Cost, fun unmarshal_cash/1);
get_capture_cost_from_status(_) ->
undefined.
unmarshal_payment_processing_invoice_payment_flow({Flow, _}) ->
Flow.
unmarshal_payment_processing_invoice_payment_payer({Payer, Data}) ->
{Payer, unmarshal_payment_processing_invoice_payment_payer_data(Data)}.
unmarshal_payment_processing_invoice_payment_payer_data(#domain_PaymentResourcePayer{
resource = #domain_DisposablePaymentResource{payment_tool = PaymentTool}
}) ->
genlib_map:compact(#{
payment_tool => maybe_unmarshal(PaymentTool, fun unmarshal_payment_processing_payment_tool/1)
});
unmarshal_payment_processing_invoice_payment_payer_data(#domain_CustomerPayer{payment_tool = PaymentTool}) ->
genlib_map:compact(#{
payment_tool => maybe_unmarshal(PaymentTool, fun unmarshal_payment_processing_payment_tool/1)
});
unmarshal_payment_processing_invoice_payment_payer_data(#domain_RecurrentPayer{payment_tool = PaymentTool}) ->
genlib_map:compact(#{
payment_tool => maybe_unmarshal(PaymentTool, fun unmarshal_payment_processing_payment_tool/1)
-define(INVOICE_PAYMENT_ADJUSTMENT(V), #context_payproc_Context{
invoice = #context_payproc_Invoice{
payment = #context_payproc_InvoicePayment{adjustment = V = #domain_InvoicePaymentAdjustment{}}
}
}).
unmarshal_payment_processing_payment_tool({bank_card, #domain_BankCard{token = Token, exp_date = ExpDate}}) ->
{bank_card, #{
token => Token,
exp_date => maybe_unmarshal(ExpDate, fun unmarshal_payment_processing_bank_card_exp_data/1)
}};
unmarshal_payment_processing_payment_tool(_) ->
undefined.
unmarshal_payment_processing_bank_card_exp_data(#domain_BankCardExpDate{month = Month, year = Year}) ->
BinaryMonth = integer_to_binary(Month),
BinaryYear = integer_to_binary(Year),
<<BinaryMonth/binary, "/", BinaryYear/binary>>.
unmarshal_payment_processing_invoice_payment_adjustment(#domain_InvoicePaymentAdjustment{
id = ID,
created_at = CreatedAt
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1)
-define(INVOICE_PAYMENT_REFUND(V), #context_payproc_Context{
invoice = #context_payproc_Invoice{
payment = #context_payproc_InvoicePayment{refund = V = #domain_InvoicePaymentRefund{}}
}
}).
unmarshal_payment_processing_invoice_payment_refund(#domain_InvoicePaymentRefund{
id = ID,
cash = Cost,
created_at = CreatedAt
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
cost => maybe_unmarshal(Cost, fun unmarshal_cash/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1)
-define(INVOICE_PAYMENT_CHARGEBACK(V), #context_payproc_Context{
invoice = #context_payproc_Invoice{
payment = #context_payproc_InvoicePayment{chargeback = V = #domain_InvoicePaymentChargeback{}}
}
}).
unmarshal_payment_processing_invoice_payment_chargeback(#domain_InvoicePaymentChargeback{
id = ID,
levy = Levy,
body = Body,
created_at = CreatedAt
}) ->
genlib_map:compact(#{
id => maybe_unmarshal(ID, fun unmarshal_string/1),
levy => maybe_unmarshal(Levy, fun unmarshal_cash/1),
body => maybe_unmarshal(Body, fun unmarshal_cash/1),
created_at => maybe_unmarshal(CreatedAt, fun unmarshal_string/1)
}).
get_owner_id(?INVOICE(Invoice)) ->
{ok, Invoice#domain_Invoice.owner_id};
get_owner_id(_) ->
{error, notfound}.
unmarshal_cash(#domain_Cash{amount = Amount, currency = #domain_CurrencyRef{symbolic_code = Currency}}) ->
#{amount => Amount, currency => Currency}.
get_shop_id(?INVOICE(Invoice)) ->
{ok, Invoice#domain_Invoice.shop_id};
get_shop_id(_) ->
{error, notfound}.
unmarshal_string(Value) ->
Value.
get_created_at(invoice, ?INVOICE(Invoice)) ->
{ok, Invoice#domain_Invoice.created_at};
get_created_at(invoice_adjustment, ?INVOICE_ADJUSTMENT(Adjustment)) ->
{ok, Adjustment#domain_InvoiceAdjustment.created_at};
get_created_at(invoice_payment, ?INVOICE_PAYMENT(Payment)) ->
{ok, Payment#domain_InvoicePayment.created_at};
get_created_at(invoice_payment_adjustment, ?INVOICE_PAYMENT_ADJUSTMENT(Adjustment)) ->
{ok, Adjustment#domain_InvoicePaymentAdjustment.created_at};
get_created_at(invoice_payment_refund, ?INVOICE_PAYMENT_REFUND(Refund)) ->
{ok, Refund#domain_InvoicePaymentRefund.created_at};
get_created_at(invoice_payment_chargeback, ?INVOICE_PAYMENT_CHARGEBACK(Chargeback)) ->
{ok, Chargeback#domain_InvoicePaymentChargeback.created_at};
get_created_at(_, _CtxInvoice) ->
{error, notfound}.
maybe_unmarshal(undefined, _) ->
undefined;
maybe_unmarshal(Value, UnmarshalFun) ->
UnmarshalFun(Value).
get_cost(invoice, ?INVOICE(Invoice)) ->
lim_payproc_utils:cash(Invoice#domain_Invoice.cost);
get_cost(invoice_payment, ?INVOICE_PAYMENT(Payment)) ->
lim_payproc_utils:cash(Payment#domain_InvoicePayment.cost);
get_cost(invoice_payment_refund, ?INVOICE_PAYMENT_REFUND(Refund)) ->
lim_payproc_utils:cash(Refund#domain_InvoicePaymentRefund.cash);
get_cost(invoice_payment_chargeback, ?INVOICE_PAYMENT_CHARGEBACK(Chargeback)) ->
lim_payproc_utils:cash(Chargeback#domain_InvoicePaymentChargeback.body);
get_cost(_, _CtxInvoice) ->
{error, notfound}.
get_capture_cost(invoice_payment, ?INVOICE_PAYMENT(Payment)) ->
get_capture_cost(Payment#domain_InvoicePayment.status);
get_capture_cost(_, _CtxInvoice) ->
{error, notfound}.
get_capture_cost({captured, #domain_InvoicePaymentCaptured{cost = Cost}}) when Cost /= undefined ->
lim_payproc_utils:cash(Cost);
get_capture_cost({_Status, _}) ->
{error, notfound}.
get_payment_tool(Operation, ?INVOICE_PAYMENT(Payment)) when
Operation == invoice_payment;
Operation == invoice_payment_adjustment;
Operation == invoice_payment_refund;
Operation == invoice_payment_chargeback
->
{_Type, Payer} = Payment#domain_InvoicePayment.payer,
get_payer_payment_tool(Payer);
get_payment_tool(_, _CtxInvoice) ->
{error, notfound}.
get_payer_payment_tool(#domain_PaymentResourcePayer{resource = #domain_DisposablePaymentResource{payment_tool = PT}}) ->
lim_payproc_utils:payment_tool(PT);
get_payer_payment_tool(#domain_CustomerPayer{payment_tool = PT}) ->
lim_payproc_utils:payment_tool(PT);
get_payer_payment_tool(#domain_RecurrentPayer{payment_tool = PT}) ->
lim_payproc_utils:payment_tool(PT).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-spec test() -> _.
-spec marshal_unmarshal_created_test() -> _.
marshal_unmarshal_created_test() ->
ExpDate = #domain_BankCardExpDate{month = 2, year = 2022},
-define(PAYMENT_W_PAYER(Payer), #domain_InvoicePayment{
id = <<"ID">>,
created_at = <<"2000-02-02T12:12:12Z">>,
status = {pending, #domain_InvoicePaymentPending{}},
cost = #domain_Cash{
amount = 42,
currency = #domain_CurrencyRef{symbolic_code = <<"CNY">>}
},
domain_revision = 42,
flow = {instant, #domain_InvoicePaymentFlowInstant{}},
payer = Payer
}).
-define(CONTEXT_PAYMENT(Payment), #context_payproc_Context{
op = {invoice_payment, #context_payproc_OperationInvoicePayment{}},
invoice = #context_payproc_Invoice{
payment = #context_payproc_InvoicePayment{
payment = Payment
}
}
}).
-spec get_payment_tool_test_() -> [_TestGen].
get_payment_tool_test_() ->
PaymentTool =
{bank_card, #domain_BankCard{
token = <<"Token">>,
bin = <<"bin">>,
exp_date = ExpDate,
bin = <<"654321">>,
exp_date = #domain_BankCardExpDate{month = 2, year = 2022},
last_digits = <<"1234">>
}},
Data0 = #domain_PaymentResourcePayer{
PaymentResourcePayer =
{payment_resource, #domain_PaymentResourcePayer{
resource = #domain_DisposablePaymentResource{payment_tool = PaymentTool},
contact_info = #domain_ContactInfo{}
},
#{payment_tool := _} = unmarshal_payment_processing_invoice_payment_payer_data(Data0),
Data1 = #domain_CustomerPayer{
}},
CustomerPayer =
{customer, #domain_CustomerPayer{
customer_id = <<"customer_id">>,
customer_binding_id = <<"customer_binding_id">>,
rec_payment_tool_id = <<"rec_payment_tool_id">>,
payment_tool = PaymentTool,
contact_info = #domain_ContactInfo{}
},
#{payment_tool := _} = unmarshal_payment_processing_invoice_payment_payer_data(Data1),
Data2 = #domain_RecurrentPayer{
}},
RecurrentPayer =
{recurrent, #domain_RecurrentPayer{
payment_tool = PaymentTool,
recurrent_parent = #domain_RecurrentParentPayment{
invoice_id = <<"invoice_id">>,
payment_id = <<"payment_id">>
},
contact_info = #domain_ContactInfo{}
},
#{payment_tool := _} = unmarshal_payment_processing_invoice_payment_payer_data(Data2),
Data3 = #domain_RecurrentPayer{
}},
ExpectedValue = {bank_card, #{token => <<"Token">>, exp_date => {2, 2022}}},
[
?_assertEqual(
{ok, ExpectedValue},
get_value(payment_tool, ?CONTEXT_PAYMENT(?PAYMENT_W_PAYER(PaymentResourcePayer)))
),
?_assertEqual(
{ok, ExpectedValue},
get_value(payment_tool, ?CONTEXT_PAYMENT(?PAYMENT_W_PAYER(CustomerPayer)))
),
?_assertEqual(
{ok, ExpectedValue},
get_value(payment_tool, ?CONTEXT_PAYMENT(?PAYMENT_W_PAYER(RecurrentPayer)))
)
].
-spec get_payment_tool_unsupported_test_() -> _TestGen.
get_payment_tool_unsupported_test_() ->
Payer =
{recurrent, #domain_RecurrentPayer{
payment_tool = {payment_terminal, #domain_PaymentTerminal{}},
recurrent_parent = #domain_RecurrentParentPayment{
invoice_id = <<"invoice_id">>,
payment_id = <<"payment_id">>
},
contact_info = #domain_ContactInfo{}
},
#{} = unmarshal_payment_processing_invoice_payment_payer_data(Data3).
}},
?_assertEqual(
{error, {unsupported, {payment_tool, payment_terminal}}},
get_value(payment_tool, ?CONTEXT_PAYMENT(?PAYMENT_W_PAYER(Payer)))
).
-endif.

View File

@ -0,0 +1,48 @@
-module(lim_payproc_utils).
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-export([cash/1]).
-export([payment_tool/1]).
-type cash() ::
lim_body:cash().
-type payment_tool() ::
{bank_card, #{
token := binary(),
exp_date := {1..12, 2000..9999} | undefined
}}
| {digital_wallet, #{
id := binary(),
service := binary()
}}.
%%
-spec cash(dmsl_domain_thrift:'Cash'()) ->
{ok, cash()}.
cash(#domain_Cash{amount = Amount, currency = #domain_CurrencyRef{symbolic_code = Currency}}) ->
{ok, #{amount => Amount, currency => Currency}}.
-spec payment_tool(dmsl_domain_thrift:'PaymentTool'()) ->
{ok, payment_tool()} | {error, {unsupported, _}}.
payment_tool({bank_card, BC}) ->
{ok,
{bank_card, #{
token => BC#domain_BankCard.token,
exp_date => get_bank_card_expdate(BC#domain_BankCard.exp_date)
}}};
payment_tool({digital_wallet, DW}) ->
{ok,
{digital_wallet, #{
id => DW#domain_DigitalWallet.id,
service => DW#domain_DigitalWallet.payment_service#domain_PaymentServiceRef.id
}}};
payment_tool({Type, _}) ->
{error, {unsupported, {payment_tool, Type}}}.
get_bank_card_expdate(#domain_BankCardExpDate{month = Month, year = Year}) ->
{Month, Year};
get_bank_card_expdate(undefined) ->
undefined.

View File

@ -1,6 +1,7 @@
-module(lim_range_codec).
-include_lib("limiter_proto/include/lim_limiter_range_thrift.hrl").
-include_lib("limiter_proto/include/limproto_range_thrift.hrl").
-include_lib("limiter_proto/include/limproto_timerange_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).
@ -20,14 +21,14 @@
-spec marshal(type_name(), decoded_value()) -> encoded_value().
marshal(timestamped_change, {ev, Timestamp, Change}) ->
#limiter_range_TimestampedChange{
#range_TimestampedChange{
change = marshal(change, Change),
occured_at = marshal(timestamp, Timestamp)
};
marshal(change, {created, Range}) ->
{created, #limiter_range_CreatedChange{limit_range = marshal(range, Range)}};
{created, #range_CreatedChange{limit_range = marshal(range, Range)}};
marshal(change, {time_range_created, TimeRange}) ->
{time_range_created, #limiter_range_TimeRangeCreatedChange{time_range = marshal(time_range, TimeRange)}};
{time_range_created, #range_TimeRangeCreatedChange{time_range = marshal(time_range, TimeRange)}};
marshal(
range,
Range = #{
@ -36,7 +37,7 @@ marshal(
created_at := CreatedAt
}
) ->
#limiter_range_LimitRange{
#range_LimitRange{
id = ID,
type = marshal(time_range_type, Type),
created_at = CreatedAt,
@ -48,7 +49,7 @@ marshal(time_range, #{
account_id_from := AccountIDFrom,
account_id_to := AccountIDTo
}) ->
#limiter_time_range_TimeRange{
#timerange_TimeRange{
upper = Upper,
lower = Lower,
account_id_from = AccountIDFrom,
@ -57,15 +58,15 @@ marshal(time_range, #{
marshal(time_range_type, {calendar, SubType}) ->
{calendar, marshal(time_range_sub_type, SubType)};
marshal(time_range_type, {interval, Interval}) ->
{interval, #limiter_time_range_TimeRangeTypeInterval{amount = Interval}};
{interval, #timerange_TimeRangeTypeInterval{amount = Interval}};
marshal(time_range_sub_type, year) ->
{year, #limiter_time_range_TimeRangeTypeCalendarYear{}};
{year, #timerange_TimeRangeTypeCalendarYear{}};
marshal(time_range_sub_type, month) ->
{month, #limiter_time_range_TimeRangeTypeCalendarMonth{}};
{month, #timerange_TimeRangeTypeCalendarMonth{}};
marshal(time_range_sub_type, week) ->
{week, #limiter_time_range_TimeRangeTypeCalendarWeek{}};
{week, #timerange_TimeRangeTypeCalendarWeek{}};
marshal(time_range_sub_type, day) ->
{day, #limiter_time_range_TimeRangeTypeCalendarDay{}};
{day, #timerange_TimeRangeTypeCalendarDay{}};
marshal(timestamp, {DateTime, USec}) ->
DateTimeinSeconds = genlib_time:daytime_to_unixtime(DateTime),
{TimeinUnit, Unit} =
@ -80,14 +81,14 @@ marshal(timestamp, {DateTime, USec}) ->
-spec unmarshal(type_name(), encoded_value()) -> decoded_value().
unmarshal(timestamped_change, TimestampedChange) ->
Timestamp = unmarshal(timestamp, TimestampedChange#limiter_range_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#limiter_range_TimestampedChange.change),
Timestamp = unmarshal(timestamp, TimestampedChange#range_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#range_TimestampedChange.change),
{ev, Timestamp, Change};
unmarshal(change, {created, #limiter_range_CreatedChange{limit_range = Range}}) ->
unmarshal(change, {created, #range_CreatedChange{limit_range = Range}}) ->
{created, unmarshal(range, Range)};
unmarshal(change, {time_range_created, #limiter_range_TimeRangeCreatedChange{time_range = Range}}) ->
unmarshal(change, {time_range_created, #range_TimeRangeCreatedChange{time_range = Range}}) ->
{time_range_created, unmarshal(time_range, Range)};
unmarshal(range, #limiter_range_LimitRange{
unmarshal(range, #range_LimitRange{
id = ID,
type = Type,
created_at = CreatedAt,
@ -99,7 +100,7 @@ unmarshal(range, #limiter_range_LimitRange{
created_at => CreatedAt,
currency => Currency
});
unmarshal(time_range, #limiter_time_range_TimeRange{
unmarshal(time_range, #timerange_TimeRange{
upper = Upper,
lower = Lower,
account_id_from = AccountIDFrom,
@ -113,7 +114,7 @@ unmarshal(time_range, #limiter_time_range_TimeRange{
};
unmarshal(time_range_type, {calendar, SubType}) ->
{calendar, unmarshal(time_range_sub_type, SubType)};
unmarshal(time_range_type, {interval, #limiter_time_range_TimeRangeTypeInterval{amount = Interval}}) ->
unmarshal(time_range_type, {interval, #timerange_TimeRangeTypeInterval{amount = Interval}}) ->
{interval, Interval};
unmarshal(time_range_sub_type, {year, _}) ->
year;

View File

@ -70,13 +70,13 @@ unmarshal(T, V, C) when
-spec marshal_event(machinery_mg_schema:version(), event(), context()) -> {machinery_msgpack:t(), context()}.
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = lim_range_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {lim_limiter_range_thrift, 'TimestampedChange'}},
Type = {struct, struct, {limproto_range_thrift, 'TimestampedChange'}},
{{bin, lim_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {lim_limiter_range_thrift, 'TimestampedChange'}},
Type = {struct, struct, {limproto_range_thrift, 'TimestampedChange'}},
ThriftChange = lim_proto_utils:deserialize(Type, EncodedThriftChange),
{lim_range_codec:unmarshal(timestamped_change, ThriftChange), Context}.
@ -98,7 +98,7 @@ marshal_unmarshal_created_test() ->
created_at => <<"2000-01-01T00:00:00Z">>,
currency => <<"USD">>
}},
Context = #{machine_ref => ID, machine_ns => limrange},
Context = #{machine_id => ID, machine_ns => limrange},
Event = {ev, lim_time:machinery_now(), Created},
{Marshaled, _} = marshal_event(1, Event, Context),
{Unmarshaled, _} = unmarshal_event(1, Marshaled, Context),
@ -113,7 +113,7 @@ marshal_unmarshal_time_range_created_test() ->
upper => <<"2000-01-01T00:00:00Z">>,
lower => <<"2000-01-01T00:00:00Z">>
}},
Context = #{machine_ref => <<"id">>, machine_ns => limrange},
Context = #{machine_id => <<"id">>, machine_ns => limrange},
Event = {ev, lim_time:machinery_now(), TimeRangeCreated},
{Marshaled, _} = marshal_event(1, Event, Context),
{Unmarshaled, _} = unmarshal_event(1, Marshaled, Context),

View File

@ -20,7 +20,7 @@
| {error, conversion_error()}.
convert(#{amount := Amount, currency := Currency}, DestinationCurrency, Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
{ok, Timestamp} = lim_context:get_from_context(ContextType, created_at, LimitContext),
{ok, Timestamp} = lim_context:get_value(ContextType, created_at, LimitContext),
Request = #rate_ConversionRequest{
source = Currency,
destination = DestinationCurrency,

View File

@ -3,7 +3,7 @@
-export([compute/4]).
-type amount() :: lim_body:amount().
-type currency() :: lim_domain_thrift:'CurrencySymbolicCode'().
-type currency() :: dmsl_domain_thrift:'CurrencySymbolicCode'().
-type stage() :: hold | commit.
-type t() :: number | {amount, currency()}.
@ -39,7 +39,7 @@ get_commit_body(Config, LimitContext) ->
case lim_body:get(partial, Config, LimitContext) of
{ok, Body} ->
Body;
{error, notfound} ->
{error, _} ->
get_body(Config, LimitContext)
end.

View File

@ -1,6 +1,6 @@
-module(lim_turnover_processor).
-include_lib("limiter_proto/include/lim_limiter_thrift.hrl").
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
-behaviour(lim_config_machine).
@ -108,13 +108,13 @@ rollback(LimitChange = #limiter_LimitChange{id = LimitID}, Config, LimitContext)
end).
compute_limit_time_range_location(LimitID, Config, LimitContext) ->
{ok, Timestamp} = lim_context:get_from_context(payment_processing, created_at, LimitContext),
Timestamp = get_timestamp(Config, LimitContext),
LimitRangeID = construct_range_id(LimitID, Timestamp, Config, LimitContext),
TimeRange = lim_config_machine:calculate_time_range(Timestamp, Config),
{LimitRangeID, TimeRange}.
ensure_limit_time_range(LimitID, Config, LimitContext) ->
{ok, Timestamp} = lim_context:get_from_context(payment_processing, created_at, LimitContext),
Timestamp = get_timestamp(Config, LimitContext),
{LimitRangeID, TimeRange} = compute_limit_time_range_location(LimitID, Config, LimitContext),
CreateParams = genlib_map:compact(#{
id => LimitRangeID,
@ -124,6 +124,11 @@ ensure_limit_time_range(LimitID, Config, LimitContext) ->
}),
unwrap(lim_range_machine:ensure_exists(CreateParams, TimeRange, LimitContext)).
get_timestamp(Config, LimitContext) ->
ContextType = lim_config_machine:context_type(Config),
{ok, Timestamp} = lim_context:get_value(ContextType, created_at, LimitContext),
Timestamp.
construct_plan_id(#limiter_LimitChange{change_id = ChangeID}) ->
% DISCUSS
ChangeID.

View File

@ -0,0 +1,73 @@
-module(lim_wthdproc_context).
-include_lib("limiter_proto/include/limproto_context_withdrawal_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_domain_thrift.hrl").
-behaviour(lim_context).
-export([get_operation/1]).
-export([get_value/2]).
-type context() :: limproto_context_withdrawal_thrift:'Context'().
-type operation() ::
withdrawal.
-export_type([operation/0]).
-export_type([context/0]).
%%
-spec get_operation(context()) -> {ok, operation()} | {error, notfound}.
get_operation(#context_withdrawal_Context{op = {Operation, _}}) ->
{ok, Operation};
get_operation(#context_withdrawal_Context{op = undefined}) ->
{error, notfound}.
-spec get_value(atom(), context()) -> {ok, term()} | {error, notfound | {unsupported, _}}.
get_value(ValueName, Context) ->
case get_operation(Context) of
{ok, Operation} ->
get_value(ValueName, Operation, Context);
{error, _} = Error ->
Error
end.
get_value(owner_id, _Operation, Context) ->
get_owner_id(Context);
get_value(created_at, Operation, Context) ->
get_created_at(Operation, Context);
get_value(cost, Operation, Context) ->
get_cost(Operation, Context);
get_value(payment_tool, Operation, Context) ->
get_payment_tool(Operation, Context);
get_value(ValueName, _Operation, _Context) ->
{error, {unsupported, ValueName}}.
-define(WITHDRAWAL(V), #context_withdrawal_Context{
withdrawal = #context_withdrawal_Withdrawal{
withdrawal = V = #wthd_domain_Withdrawal{}
}
}).
get_owner_id(?WITHDRAWAL(Wthd)) ->
Identity = Wthd#wthd_domain_Withdrawal.sender,
{ok, Identity#wthd_domain_Identity.owner_id};
get_owner_id(_CtxWithdrawal) ->
{error, notfound}.
get_created_at(withdrawal, ?WITHDRAWAL(Wthd)) ->
{ok, Wthd#wthd_domain_Withdrawal.created_at};
get_created_at(_, _CtxWithdrawal) ->
{error, notfound}.
get_cost(withdrawal, ?WITHDRAWAL(Wthd)) ->
Body = Wthd#wthd_domain_Withdrawal.body,
lim_payproc_utils:cash(Body);
get_cost(_, _CtxWithdrawal) ->
{error, notfound}.
get_payment_tool(withdrawal, ?WITHDRAWAL(Wthd)) ->
Destination = Wthd#wthd_domain_Withdrawal.destination,
lim_payproc_utils:payment_tool(Destination);
get_payment_tool(_, _CtxWithdrawal) ->
{error, notfound}.

View File

@ -5,7 +5,6 @@
{applications, [
kernel,
stdlib,
damsel,
limiter_proto,
xrates_proto,
machinery,

View File

@ -91,11 +91,11 @@ get_handler_specs(ServiceOpts) ->
[
{
maps:get(path, LimiterService, <<"/v1/limiter">>),
{{lim_limiter_thrift, 'Limiter'}, lim_handler}
{{limproto_limiter_thrift, 'Limiter'}, lim_handler}
},
{
maps:get(path, ConfiguratorService, <<"/v1/configurator">>),
{{lim_configurator_thrift, 'Configurator'}, lim_configurator}
{{limproto_configurator_thrift, 'Configurator'}, lim_configurator}
}
].

View File

@ -1,11 +1,12 @@
-module(lim_client).
-include_lib("limiter_proto/include/lim_limiter_thrift.hrl").
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
-export([new/0]).
-export([get/3]).
-export([hold/3]).
-export([commit/3]).
-export([rollback/3]).
-export([legacy_create_config/2]).
-export([create_config/2]).
@ -13,12 +14,12 @@
-type client() :: woody_context:ctx().
-type limit_id() :: lim_limiter_thrift:'LimitID'().
-type limit_change() :: lim_limiter_thrift:'LimitChange'().
-type limit_context() :: lim_limiter_thrift:'LimitContext'().
-type clock() :: lim_limiter_thrift:'Clock'().
-type legacy_create_params() :: lim_configurator_thrift:'LimitCreateParams'().
-type limit_config_params() :: lim_limiter_config_thrift:'LimitConfigParams'().
-type limit_id() :: limproto_limiter_thrift:'LimitID'().
-type limit_change() :: limproto_limiter_thrift:'LimitChange'().
-type limit_context() :: limproto_limiter_thrift:'LimitContext'().
-type clock() :: limproto_limiter_thrift:'Clock'().
-type legacy_create_params() :: limproto_configurator_thrift:'LimitCreateParams'().
-type limit_config_params() :: limproto_config_thrift:'LimitConfigParams'().
%%% API
@ -38,6 +39,10 @@ hold(LimitChange, Context, Client) ->
commit(LimitChange, Context, Client) ->
call('Commit', {LimitChange, clock(), Context}, Client).
-spec rollback(limit_change(), limit_context(), client()) -> woody:result() | no_return().
rollback(LimitChange, Context, Client) ->
call('Rollback', {LimitChange, clock(), Context}, Client).
%%
-spec legacy_create_config(legacy_create_params(), client()) -> woody:result() | no_return().
@ -56,7 +61,7 @@ get_config(LimitConfigID, Client) ->
-spec call(atom(), tuple(), client()) -> woody:result() | no_return().
call(Function, Args, Client) ->
Call = {{lim_limiter_thrift, 'Limiter'}, Function, Args},
Call = {{limproto_limiter_thrift, 'Limiter'}, Function, Args},
Opts = #{
url => <<"http://limiter:8022/v1/limiter">>,
event_handler => scoper_woody_event_handler,
@ -68,7 +73,7 @@ call(Function, Args, Client) ->
-spec call_configurator(atom(), tuple(), client()) -> woody:result() | no_return().
call_configurator(Function, Args, Client) ->
Call = {{lim_configurator_thrift, 'Configurator'}, Function, Args},
Call = {{limproto_configurator_thrift, 'Configurator'}, Function, Args},
Opts = #{
url => <<"http://limiter:8022/v1/configurator">>,
event_handler => scoper_woody_event_handler,

View File

@ -2,7 +2,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("stdlib/include/assert.hrl").
-include_lib("limiter_proto/include/lim_configurator_thrift.hrl").
-include_lib("limiter_proto/include/limproto_configurator_thrift.hrl").
-include("lim_ct_helper.hrl").
-export([all/0]).
@ -17,6 +17,7 @@
-export([create_config/1]).
-export([create_config_single_scope/1]).
-export([get_config/1]).
-export([get_inexistent_config/1]).
-type group_name() :: atom().
-type test_case_name() :: atom().
@ -36,7 +37,8 @@ groups() ->
legacy_create_config,
create_config,
create_config_single_scope,
get_config
get_config,
get_inexistent_config
]}
].
@ -81,14 +83,14 @@ legacy_create_config(C) ->
Client = lim_client:new(),
ID = ?config(limit_id, C),
Description = genlib:unique(),
Params = #limiter_configurator_LimitCreateParams{
Params = #configurator_LimitCreateParams{
id = ID,
name = <<"GlobalMonthTurnover">>,
description = Description,
started_at = <<"2000-01-01T00:00:00Z">>
},
?assertMatch(
{ok, #limiter_config_LimitConfig{
{ok, #config_LimitConfig{
id = ID,
description = Description
}},
@ -100,7 +102,7 @@ create_config(C) ->
Client = lim_client:new(),
ID = ?config(limit_id, C),
Description = genlib:unique(),
Params = #limiter_config_LimitConfigParams{
Params = #config_LimitConfigParams{
id = ?config(limit_id, C),
description = Description,
started_at = <<"2000-01-01T00:00:00Z">>,
@ -115,7 +117,7 @@ create_config(C) ->
context_type = ?ctx_type_payproc()
},
?assertMatch(
{ok, #limiter_config_LimitConfig{
{ok, #config_LimitConfig{
id = ID,
description = Description
}},
@ -125,7 +127,7 @@ create_config(C) ->
-spec create_config_single_scope(config()) -> _.
create_config_single_scope(C) ->
Client = lim_client:new(),
Params = #limiter_config_LimitConfigParams{
Params = #config_LimitConfigParams{
id = ?config(limit_id, C),
started_at = <<"2000-01-01T00:00:00Z">>,
time_range_type = ?time_range_week(),
@ -135,7 +137,7 @@ create_config_single_scope(C) ->
context_type = ?ctx_type_payproc(),
op_behaviour = ?op_behaviour()
},
{ok, #limiter_config_LimitConfig{
{ok, #config_LimitConfig{
scope = Scope
}} = lim_client:create_config(Params, Client),
?assertEqual(?scope([?scope_party()]), Scope).
@ -144,13 +146,20 @@ create_config_single_scope(C) ->
get_config(C) ->
ID = ?config(limit_id, C),
#{client := Client} = prepare_environment(ID, <<"GlobalMonthTurnover">>, C),
{ok, #limiter_config_LimitConfig{id = ID}} = lim_client:get_config(ID, Client).
{ok, #config_LimitConfig{id = ID}} = lim_client:get_config(ID, Client).
-spec get_inexistent_config(config()) -> _.
get_inexistent_config(_C) ->
?assertEqual(
{exception, #configurator_LimitConfigNotFound{}},
lim_client:get_config(<<"NOSUCHCONFIG">>, lim_client:new())
).
%%
prepare_environment(ID, LimitName, _C) ->
Client = lim_client:new(),
Params = #limiter_configurator_LimitCreateParams{
Params = #configurator_LimitCreateParams{
id = ID,
name = LimitName,
description = <<"description">>,

View File

@ -1,7 +1,13 @@
-ifndef(__limiter_ct_helper__).
-define(__limiter_ct_helper__, 42).
-include_lib("limiter_proto/include/lim_configurator_thrift.hrl").
-include_lib("limiter_proto/include/limproto_config_thrift.hrl").
-include_lib("limiter_proto/include/limproto_timerange_thrift.hrl").
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
-include_lib("limiter_proto/include/limproto_context_payproc_thrift.hrl").
-include_lib("limiter_proto/include/limproto_context_withdrawal_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_domain_thrift.hrl").
-define(currency, <<"RUB">>).
-define(string, <<"STRING">>).
@ -16,126 +22,83 @@
-define(scope(Types), {multi, ordsets:from_list(Types)}).
-define(global(), ?scope([])).
-define(scope_party(), {party, #limiter_config_LimitScopeEmptyDetails{}}).
-define(scope_shop(), {shop, #limiter_config_LimitScopeEmptyDetails{}}).
-define(scope_payment_tool(), {payment_tool, #limiter_config_LimitScopeEmptyDetails{}}).
-define(scope_party(), {party, #config_LimitScopeEmptyDetails{}}).
-define(scope_shop(), {shop, #config_LimitScopeEmptyDetails{}}).
-define(scope_payment_tool(), {payment_tool, #config_LimitScopeEmptyDetails{}}).
-define(lim_type_turnover(), ?lim_type_turnover(?turnover_metric_number())).
-define(lim_type_turnover(Metric),
{turnover, #limiter_config_LimitTypeTurnover{metric = Metric}}
{turnover, #config_LimitTypeTurnover{metric = Metric}}
).
-define(turnover_metric_number(), {number, #limiter_config_LimitTurnoverNumber{}}).
-define(turnover_metric_number(), {number, #config_LimitTurnoverNumber{}}).
-define(turnover_metric_amount(), ?turnover_metric_amount(?currency)).
-define(turnover_metric_amount(Currency),
{amount, #limiter_config_LimitTurnoverAmount{currency = Currency}}
{amount, #config_LimitTurnoverAmount{currency = Currency}}
).
-define(time_range_day(),
{calendar, {day, #limiter_time_range_TimeRangeTypeCalendarDay{}}}
{calendar, {day, #timerange_TimeRangeTypeCalendarDay{}}}
).
-define(time_range_week(),
{calendar, {week, #limiter_time_range_TimeRangeTypeCalendarWeek{}}}
{calendar, {week, #timerange_TimeRangeTypeCalendarWeek{}}}
).
-define(time_range_month(),
{calendar, {month, #limiter_time_range_TimeRangeTypeCalendarMonth{}}}
{calendar, {month, #timerange_TimeRangeTypeCalendarMonth{}}}
).
-define(time_range_year(),
{calendar, {year, #limiter_time_range_TimeRangeTypeCalendarYear{}}}
{calendar, {year, #timerange_TimeRangeTypeCalendarYear{}}}
).
-define(op_behaviour(), ?op_behaviour(?op_addition())).
-define(op_behaviour(Refund), #limiter_config_OperationLimitBehaviour{
-define(op_behaviour(Refund), #config_OperationLimitBehaviour{
invoice_payment_refund = Refund
}).
-define(op_addition(), {addition, #limiter_config_Addition{}}).
-define(op_subtraction(), {subtraction, #limiter_config_Subtraction{}}).
-define(op_addition(), {addition, #config_Addition{}}).
-define(op_subtraction(), {subtraction, #config_Subtraction{}}).
-define(ctx_type_payproc(),
{payment_processing, #limiter_config_LimitContextTypePaymentProcessing{}}
{payment_processing, #config_LimitContextTypePaymentProcessing{}}
).
-define(op_invoice(), {invoice, #limiter_context_PaymentProcessingOperationInvoice{}}).
-define(op_invoice_payment(), {invoice_payment, #limiter_context_PaymentProcessingOperationInvoicePayment{}}).
-define(ctx_invoice(Cost), #limiter_context_LimitContext{
limiter_payment_processing = #limiter_context_ContextPaymentProcessing{
op = ?op_invoice(),
invoice = #limiter_context_Invoice{
created_at = <<"2000-01-01T00:00:00Z">>,
cost = Cost
}
}
}).
-define(ctx_invoice_payment(Cost, CaptureCost), ?ctx_invoice_payment(undefined, undefined, Cost, CaptureCost)).
-define(ctx_invoice_payment(OwnerID, ShopID, Cost, CaptureCost), #limiter_context_LimitContext{
limiter_payment_processing = #limiter_context_ContextPaymentProcessing{
op = ?op_invoice_payment(),
invoice = #limiter_context_Invoice{
owner_id = OwnerID,
shop_id = ShopID,
effective_payment = #limiter_context_InvoicePayment{
created_at = <<"2000-01-01T00:00:00Z">>,
cost = Cost,
capture_cost = CaptureCost,
flow = {hold, #limiter_context_InvoicePaymentFlowHold{}},
payer = {payment_resource, #limiter_context_PaymentResourcePayer{}},
effective_adjustment = #limiter_context_InvoicePaymentAdjustment{},
effective_chargeback = #limiter_context_InvoicePaymentChargeback{}
},
effective_adjustment = #limiter_context_InvoiceAdjustment{}
}
}
}).
-define(ctx_invoice_payment(Payment), #limiter_context_LimitContext{
limiter_payment_processing = #limiter_context_ContextPaymentProcessing{
op = ?op_invoice_payment(),
invoice = #limiter_context_Invoice{
effective_payment = Payment
}
}
}).
-define(ctx_invoice_payment_refund(OwnerID, ShopID, Cost, CaptureCost, RefundCost), #limiter_context_LimitContext{
limiter_payment_processing = #limiter_context_ContextPaymentProcessing{
op = {invoice_payment_refund, #limiter_context_PaymentProcessingOperationInvoicePaymentRefund{}},
invoice = #limiter_context_Invoice{
owner_id = OwnerID,
shop_id = ShopID,
effective_payment = #limiter_context_InvoicePayment{
created_at = <<"2000-01-01T00:00:00Z">>,
cost = Cost,
capture_cost = CaptureCost,
effective_refund = #limiter_context_InvoicePaymentRefund{
cost = RefundCost,
created_at = <<"2000-01-01T00:00:00Z">>
}
}
}
}
}).
-define(ctx_type_wthdproc(),
{withdrawal_processing, #config_LimitContextTypeWithdrawalProcessing{}}
).
%% Payproc
-define(payproc_op_invoice, {invoice, #limiter_context_payproc_OperationInvoice{}}).
-define(payproc_op_invoice_payment, {invoice_payment, #limiter_context_payproc_OperationInvoicePayment{}}).
-define(op_invoice, {invoice, #context_payproc_OperationInvoice{}}).
-define(op_payment, {invoice_payment, #context_payproc_OperationInvoicePayment{}}).
-define(op_refund, {invoice_payment_refund, #context_payproc_OperationInvoicePaymentRefund{}}).
-define(payproc_bank_card(),
?payproc_bank_card(?string, 2, 2022)
-define(bank_card(), ?bank_card(?string, 2, 2022)).
-define(bank_card(Token),
{bank_card, #domain_BankCard{
token = Token,
bin = ?string,
last_digits = ?string
}}
).
-define(payproc_bank_card(Token, Month, Year), #domain_BankCard{
-define(bank_card(Token, Month, Year),
{bank_card, #domain_BankCard{
token = Token,
bin = ?string,
last_digits = ?string,
exp_date = #domain_BankCardExpDate{month = Month, year = Year}
}).
}}
).
-define(payproc_invoice(OwnerID, ShopID, Cost), #domain_Invoice{
-define(digital_wallet(ID, Service),
{digital_wallet, #domain_DigitalWallet{
id = ID,
payment_service = #domain_PaymentServiceRef{id = Service}
}}
).
-define(invoice(OwnerID, ShopID, Cost), #domain_Invoice{
id = ?string,
owner_id = OwnerID,
shop_id = ShopID,
@ -146,13 +109,17 @@
cost = Cost
}).
-define(payproc_invoice_payment(Cost, CaptureCost),
?payproc_invoice_payment(Cost, CaptureCost, {bank_card, ?payproc_bank_card()})
-define(invoice_payment(Cost, CaptureCost),
?invoice_payment(Cost, CaptureCost, ?bank_card())
).
-define(payproc_invoice_payment(Cost, CaptureCost, PaymentTool), #domain_InvoicePayment{
-define(invoice_payment(Cost, CaptureCost, PaymentTool),
?invoice_payment(Cost, CaptureCost, PaymentTool, ?timestamp)
).
-define(invoice_payment(Cost, CaptureCost, PaymentTool, CreatedAt), #domain_InvoicePayment{
id = ?string,
created_at = ?timestamp,
created_at = CreatedAt,
status = {captured, #domain_InvoicePaymentCaptured{cost = CaptureCost}},
cost = Cost,
domain_revision = 1,
@ -166,51 +133,50 @@
}}
}).
-define(payproc_ctx_invoice(Cost), #limiter_context_LimitContext{
payment_processing = #limiter_context_payproc_Context{
op = ?payproc_op_invoice,
invoice = #limiter_context_payproc_Invoice{
invoice = ?payproc_invoice(?string, ?string, Cost)
-define(payproc_ctx_invoice(Cost), #limiter_LimitContext{
payment_processing = #context_payproc_Context{
op = ?op_invoice,
invoice = #context_payproc_Invoice{
invoice = ?invoice(?string, ?string, Cost)
}
}
}).
-define(payproc_ctx_invoice_payment(Cost, CaptureCost),
?payproc_ctx_invoice_payment(?string, ?string, Cost, CaptureCost)
-define(payproc_ctx_payment(Cost, CaptureCost),
?payproc_ctx_payment(?string, ?string, Cost, CaptureCost)
).
-define(payproc_ctx_invoice_payment(OwnerID, ShopID, Cost, CaptureCost), #limiter_context_LimitContext{
payment_processing = #limiter_context_payproc_Context{
op = ?payproc_op_invoice_payment,
invoice = #limiter_context_payproc_Invoice{
invoice = ?payproc_invoice(OwnerID, ShopID, Cost),
payment = #limiter_context_payproc_InvoicePayment{
payment = ?payproc_invoice_payment(Cost, CaptureCost)
-define(payproc_ctx_payment(OwnerID, ShopID, Cost, CaptureCost), #limiter_LimitContext{
payment_processing = #context_payproc_Context{
op = ?op_payment,
invoice = #context_payproc_Invoice{
invoice = ?invoice(OwnerID, ShopID, Cost),
payment = #context_payproc_InvoicePayment{
payment = ?invoice_payment(Cost, CaptureCost)
}
}
}
}).
-define(payproc_ctx_invoice_payment(Payment), #limiter_context_LimitContext{
payment_processing = #limiter_context_payproc_Context{
op = ?payproc_op_invoice_payment,
invoice = #limiter_context_payproc_Invoice{
invoice = ?payproc_invoice(?string, ?string, ?cash(10)),
payment = #limiter_context_payproc_InvoicePayment{
-define(payproc_ctx_payment(Payment), #limiter_LimitContext{
payment_processing = #context_payproc_Context{
op = ?op_payment,
invoice = #context_payproc_Invoice{
invoice = ?invoice(?string, ?string, ?cash(10)),
payment = #context_payproc_InvoicePayment{
payment = Payment
}
}
}
}).
-define(payproc_ctx_invoice_payment_refund(OwnerID, ShopID, Cost, CaptureCost, RefundCost),
#limiter_context_LimitContext{
payment_processing = #limiter_context_payproc_Context{
op = {invoice_payment_refund, #limiter_context_payproc_OperationInvoicePaymentRefund{}},
invoice = #limiter_context_payproc_Invoice{
invoice = ?payproc_invoice(OwnerID, ShopID, Cost),
payment = #limiter_context_payproc_InvoicePayment{
payment = ?payproc_invoice_payment(Cost, CaptureCost),
-define(payproc_ctx_refund(OwnerID, ShopID, Cost, CaptureCost, RefundCost), #limiter_LimitContext{
payment_processing = #context_payproc_Context{
op = ?op_refund,
invoice = #context_payproc_Invoice{
invoice = ?invoice(OwnerID, ShopID, Cost),
payment = #context_payproc_InvoicePayment{
payment = ?invoice_payment(Cost, CaptureCost),
refund = #domain_InvoicePaymentRefund{
id = ?string,
status = {succeeded, #domain_InvoicePaymentRefundSucceeded{}},
@ -221,7 +187,33 @@
}
}
}
}).
%% Wthdproc
-define(identity(OwnerID), #wthd_domain_Identity{
id = OwnerID,
owner_id = OwnerID
}).
-define(withdrawal(Body), ?withdrawal(Body, ?bank_card(), ?string)).
-define(withdrawal(Body, Destination, OwnerID), #wthd_domain_Withdrawal{
body = Body,
created_at = ?timestamp,
destination = Destination,
sender = ?identity(OwnerID)
}).
-define(op_withdrawal, {withdrawal, #context_withdrawal_OperationWithdrawal{}}).
-define(wthdproc_ctx_withdrawal(Cost), #limiter_LimitContext{
withdrawal_processing = #context_withdrawal_Context{
op = ?op_withdrawal,
withdrawal = #context_withdrawal_Withdrawal{
withdrawal = ?withdrawal(Cost)
}
).
}
}).
-endif.

View File

@ -2,10 +2,8 @@
-include_lib("stdlib/include/assert.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("lim_ct_helper.hrl").
-include_lib("limiter_proto/include/lim_configurator_thrift.hrl").
-include_lib("xrates_proto/include/xrates_rate_thrift.hrl").
-include_lib("damsel/include/dmsl_base_thrift.hrl").
-include("lim_ct_helper.hrl").
-export([all/0]).
@ -18,17 +16,18 @@
-export([commit_with_default_exchange/1]).
-export([partial_commit_with_exchange/1]).
-export([commit_with_exchange/1]).
-export([get_rate/1]).
-export([get_limit_ok/1]).
-export([get_limit_notfound/1]).
-export([hold_ok/1]).
-export([commit_ok/1]).
-export([rollback_ok/1]).
-export([partial_zero_commit_rollbacks/1]).
-export([refund_ok/1]).
-export([get_config_ok/1]).
-export([commit_inexistent_hold_fails/1]).
-export([partial_commit_inexistent_hold_fails/1]).
-export([commit_multirange_limit_ok/1]).
-export([commit_with_payment_tool_scope_ok/1]).
-export([commit_processes_idempotently/1]).
-export([full_commit_processes_idempotently/1]).
@ -40,23 +39,16 @@
-export([commit_refund_keep_number_unchanged/1]).
-export([partial_commit_number_counts_as_single_op/1]).
-export([payproc_hold_ok/1]).
-export([payproc_commit_ok/1]).
-export([payproc_rollback_ok/1]).
-export([payproc_refund_ok/1]).
-export([payproc_commit_with_payment_tool_scope_ok/1]).
-type group_name() :: atom().
-type test_case_name() :: atom().
-define(RATE_SOURCE_ID, <<"dummy_source_id">>).
%% tests descriptions
-spec all() -> [{group, group_name()}].
all() ->
[
{group, default},
{group, withdrawals},
{group, cashless},
{group, idempotency}
].
@ -68,22 +60,24 @@ groups() ->
commit_with_default_exchange,
partial_commit_with_exchange,
commit_with_exchange,
get_rate,
get_limit_ok,
get_limit_notfound,
hold_ok,
commit_ok,
rollback_ok,
partial_zero_commit_rollbacks,
get_config_ok,
refund_ok,
commit_inexistent_hold_fails,
partial_commit_inexistent_hold_fails,
commit_multirange_limit_ok,
payproc_hold_ok,
payproc_commit_ok,
payproc_rollback_ok,
payproc_refund_ok,
payproc_commit_with_payment_tool_scope_ok
commit_with_payment_tool_scope_ok
]},
{withdrawals, [parallel], [
get_limit_ok,
hold_ok,
commit_ok,
rollback_ok
]},
{cashless, [parallel], [
commit_number_ok,
@ -155,18 +149,8 @@ commit_with_default_exchange(C) ->
Rational = #base_Rational{p = 1000000, q = 100},
_ = mock_exchange(Rational, C),
ID = configure_limit(?time_range_month(), ?global(), C),
Context = #limiter_context_LimitContext{
limiter_payment_processing = #limiter_context_ContextPaymentProcessing{
op = {invoice, #limiter_context_PaymentProcessingOperationInvoice{}},
invoice = #limiter_context_Invoice{
created_at = <<"2000-01-01T00:00:00Z">>,
cost = #domain_Cash{
amount = 10000,
currency = #domain_CurrencyRef{symbolic_code = <<"SOME_CURRENCY">>}
}
}
}
},
Cost = ?cash(10000, <<"SOME_CURRENCY">>),
Context = ?payproc_ctx_invoice(Cost),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID), Context, ?config(client, C)),
{ok, #limiter_Limit{amount = 10000}} = lim_client:get(ID, Context, ?config(client, C)).
@ -175,24 +159,9 @@ partial_commit_with_exchange(C) ->
Rational = #base_Rational{p = 800000, q = 100},
_ = mock_exchange(Rational, C),
ID = configure_limit(?time_range_month(), ?global(), C),
Context = #limiter_context_LimitContext{
limiter_payment_processing = #limiter_context_ContextPaymentProcessing{
op = {invoice_payment, #limiter_context_PaymentProcessingOperationInvoicePayment{}},
invoice = #limiter_context_Invoice{
effective_payment = #limiter_context_InvoicePayment{
created_at = <<"2000-01-01T00:00:00Z">>,
cost = #domain_Cash{
amount = 10000,
currency = #domain_CurrencyRef{symbolic_code = <<"USD">>}
},
capture_cost = #domain_Cash{
amount = 8000,
currency = #domain_CurrencyRef{symbolic_code = <<"USD">>}
}
}
}
}
},
Cost = ?cash(1000, <<"USD">>),
CaptureCost = ?cash(800, <<"USD">>),
Context = ?payproc_ctx_payment(Cost, CaptureCost),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID), Context, ?config(client, C)),
{ok, #limiter_Limit{amount = 8400}} = lim_client:get(ID, Context, ?config(client, C)).
@ -201,43 +170,19 @@ commit_with_exchange(C) ->
Rational = #base_Rational{p = 1000000, q = 100},
_ = mock_exchange(Rational, C),
ID = configure_limit(?time_range_month(), ?global(), C),
Context = #limiter_context_LimitContext{
limiter_payment_processing = #limiter_context_ContextPaymentProcessing{
op = {invoice, #limiter_context_PaymentProcessingOperationInvoice{}},
invoice = #limiter_context_Invoice{
created_at = <<"2000-01-01T00:00:00Z">>,
cost = #domain_Cash{
amount = 10000,
currency = #domain_CurrencyRef{symbolic_code = <<"USD">>}
}
}
}
},
Cost = ?cash(10000, <<"USD">>),
Context = ?payproc_ctx_invoice(Cost),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID), Context, ?config(client, C)),
{ok, #limiter_Limit{amount = 10500}} = lim_client:get(ID, Context, ?config(client, C)).
-spec get_rate(config()) -> _.
get_rate(C) ->
Rational = #base_Rational{p = 10, q = 10},
_ = mock_exchange(Rational, C),
Request = #rate_ConversionRequest{
source = <<"RUB">>,
destination = <<"USD">>,
amount = 100,
datetime = <<"Timestamp">>
},
WoodyContext = woody_context:new(),
{ok, Rational} = lim_client_woody:call(
xrates,
'GetConvertedAmount',
{?RATE_SOURCE_ID, Request},
WoodyContext
).
-spec get_limit_ok(config()) -> _.
get_limit_ok(C) ->
ID = configure_limit(?time_range_month(), ?global(), C),
Context = ?ctx_invoice(_Cost = undefined),
Context =
case get_group_name(C) of
default -> ?payproc_ctx_invoice(?cash(0));
withdrawals -> ?wthdproc_ctx_withdrawal(?cash(0))
end,
?assertMatch(
{ok, #limiter_Limit{amount = 0}},
lim_client:get(ID, Context, ?config(client, C))
@ -245,7 +190,7 @@ get_limit_ok(C) ->
-spec get_limit_notfound(config()) -> _.
get_limit_notfound(C) ->
Context = ?ctx_invoice(_Cost = undefined),
Context = ?payproc_ctx_invoice(?cash(0)),
?assertEqual(
{exception, #limiter_LimitNotFound{}},
lim_client:get(<<"NOSUCHLIMITID">>, Context, ?config(client, C))
@ -254,36 +199,50 @@ get_limit_notfound(C) ->
-spec hold_ok(config()) -> _.
hold_ok(C) ->
ID = configure_limit(?time_range_month(), ?global(), C),
Context = ?ctx_invoice(?cash(10)),
Context =
case get_group_name(C) of
default -> ?payproc_ctx_invoice(?cash(10));
withdrawals -> ?wthdproc_ctx_withdrawal(?cash(10))
end,
{ok, {vector, #limiter_VectorClock{}}} = lim_client:hold(?LIMIT_CHANGE(ID), Context, ?config(client, C)),
{ok, #limiter_Limit{}} = lim_client:get(ID, Context, ?config(client, C)).
-spec commit_ok(config()) -> _.
commit_ok(C) ->
ID = configure_limit(?time_range_month(), ?global(), C),
Context = #limiter_context_LimitContext{
limiter_payment_processing = #limiter_context_ContextPaymentProcessing{
op = {invoice, #limiter_context_PaymentProcessingOperationInvoice{}},
invoice = #limiter_context_Invoice{
created_at = <<"2000-01-01T00:00:00Z">>,
cost = #domain_Cash{
amount = 10,
currency = #domain_CurrencyRef{symbolic_code = <<"RUB">>}
}
}
}
},
Context =
case get_group_name(C) of
default -> ?payproc_ctx_invoice(?cash(10, <<"RUB">>));
withdrawals -> ?wthdproc_ctx_withdrawal(?cash(10, <<"RUB">>))
end,
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID), Context, ?config(client, C)),
{ok, #limiter_Limit{}} = lim_client:get(ID, Context, ?config(client, C)).
-spec rollback_ok(config()) -> _.
rollback_ok(C) ->
ID = configure_limit(?time_range_week(), ?global(), C),
Context0 = ?ctx_invoice_payment(?cash(10), ?cash(10)),
Context1 = ?ctx_invoice_payment(?cash(10), ?cash(0)),
Context =
case get_group_name(C) of
default -> ?payproc_ctx_invoice(?cash(10, <<"RUB">>));
withdrawals -> ?wthdproc_ctx_withdrawal(?cash(10, <<"RUB">>))
end,
Change = ?LIMIT_CHANGE(ID),
{ok, {vector, _}} = lim_client:hold(Change, Context, ?config(client, C)),
{ok, {vector, _}} = lim_client:rollback(Change, Context, ?config(client, C)).
-spec partial_zero_commit_rollbacks(config()) -> _.
partial_zero_commit_rollbacks(C) ->
ID = configure_limit(?time_range_week(), ?global(), C),
Context0 = ?payproc_ctx_payment(?cash(10), ?cash(10)),
Context1 = ?payproc_ctx_payment(?cash(10), ?cash(0)),
Change = ?LIMIT_CHANGE(ID),
{ok, {vector, _}} = lim_client:hold(Change, Context0, ?config(client, C)),
{ok, {vector, _}} = lim_client:commit(Change, Context1, ?config(client, C)).
{ok, {vector, _}} = lim_client:commit(Change, Context1, ?config(client, C)),
% NOTE
% Successful rollback here means that partial commit with zero is handled exactly
% like rollback, thus subsequent rollback succeeds idempotently. This is a backwards
% compatibility measure.
{ok, {vector, _}} = lim_client:rollback(Change, Context0, ?config(client, C)).
-spec refund_ok(config()) -> _.
refund_ok(C) ->
@ -291,8 +250,8 @@ refund_ok(C) ->
OwnerID = <<"WWWcool Ltd">>,
ShopID = <<"shop">>,
ID = configure_limit(?time_range_day(), ?scope([?scope_party(), ?scope_shop()]), C),
Context0 = ?ctx_invoice_payment(OwnerID, ShopID, ?cash(15), ?cash(15)),
RefundContext1 = ?ctx_invoice_payment_refund(OwnerID, ShopID, ?cash(10), ?cash(10), ?cash(10)),
Context0 = ?payproc_ctx_payment(OwnerID, ShopID, ?cash(15), ?cash(15)),
RefundContext1 = ?payproc_ctx_refund(OwnerID, ShopID, ?cash(10), ?cash(10), ?cash(10)),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID, <<"Payment">>), Context0, Client),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID, <<"Refund">>), RefundContext1, Client),
{ok, #limiter_Limit{} = Limit2} = lim_client:get(ID, RefundContext1, Client),
@ -301,33 +260,33 @@ refund_ok(C) ->
-spec get_config_ok(config()) -> _.
get_config_ok(C) ->
ID = configure_limit(?time_range_week(), ?global(), C),
{ok, #limiter_config_LimitConfig{}} = lim_client:get_config(ID, ?config(client, C)).
{ok, #config_LimitConfig{}} = lim_client:get_config(ID, ?config(client, C)).
-spec commit_inexistent_hold_fails(config()) -> _.
commit_inexistent_hold_fails(C) ->
ID = configure_limit(?time_range_week(), ?global(), C),
Context = ?ctx_invoice_payment(?cash(42), undefined),
Context = ?payproc_ctx_payment(?cash(42), undefined),
% NOTE
% We do not expect `LimitChangeNotFound` here because we no longer reconcile with accounter
% before requesting him to hold / commit.
{exception, #'InvalidRequest'{}} =
{exception, #base_InvalidRequest{}} =
lim_client:commit(?LIMIT_CHANGE(ID), Context, ?config(client, C)).
-spec partial_commit_inexistent_hold_fails(config()) -> _.
partial_commit_inexistent_hold_fails(C) ->
ID = configure_limit(?time_range_week(), ?global(), C),
Context = ?ctx_invoice_payment(?cash(42), ?cash(21)),
Context = ?payproc_ctx_payment(?cash(42), ?cash(21)),
% NOTE
% We do not expect `LimitChangeNotFound` here because we no longer reconcile with accounter
% before requesting him to hold / commit.
{exception, #'InvalidRequest'{}} =
{exception, #base_InvalidRequest{}} =
lim_client:commit(?LIMIT_CHANGE(ID), Context, ?config(client, C)).
-spec commit_multirange_limit_ok(config()) -> _.
commit_multirange_limit_ok(C) ->
ID = ?config(id, C),
Client = ?config(client, C),
Params = #limiter_config_LimitConfigParams{
Params = #config_LimitConfigParams{
id = ID,
started_at = <<"2000-01-01T00:00:00Z">>,
shard_size = 12,
@ -335,30 +294,52 @@ commit_multirange_limit_ok(C) ->
context_type = ?ctx_type_payproc(),
type = ?lim_type_turnover(?turnover_metric_amount(<<"RUB">>)),
scope = ?scope([]),
op_behaviour = #limiter_config_OperationLimitBehaviour{}
op_behaviour = #config_OperationLimitBehaviour{}
},
{ok, _LimitConfig} = lim_client:create_config(Params, Client),
% NOTE
% Expecting those 3 changes will be accounted in the same limit range machine.
% We have no way to verify it here though.
PaymentJan = #limiter_context_InvoicePayment{
created_at = <<"2020-01-01T00:00:00Z">>,
cost = ?cash(42)
},
{ok, _} = hold_and_commit(?LIMIT_CHANGE(ID, 1), ?ctx_invoice_payment(PaymentJan), Client),
PaymentFeb = #limiter_context_InvoicePayment{
created_at = <<"2020-02-01T00:00:00Z">>,
cost = ?cash(43)
},
{ok, _} = hold_and_commit(?LIMIT_CHANGE(ID, 2), ?ctx_invoice_payment(PaymentFeb), Client),
PaymentApr = #limiter_context_InvoicePayment{
created_at = <<"2020-04-01T00:00:00Z">>,
cost = ?cash(44)
},
{ok, _} = hold_and_commit(?LIMIT_CHANGE(ID, 3), ?ctx_invoice_payment(PaymentApr), Client),
{ok, #limiter_Limit{amount = 42}} = lim_client:get(ID, ?ctx_invoice_payment(PaymentJan), Client),
{ok, #limiter_Limit{amount = 43}} = lim_client:get(ID, ?ctx_invoice_payment(PaymentFeb), Client),
{ok, #limiter_Limit{amount = 44}} = lim_client:get(ID, ?ctx_invoice_payment(PaymentApr), Client).
PaymentJan = ?invoice_payment(?cash(42), ?cash(42), ?bank_card(), <<"2020-01-01T00:00:00Z">>),
{ok, _} = hold_and_commit(?LIMIT_CHANGE(ID, 1), ?payproc_ctx_payment(PaymentJan), Client),
PaymentFeb = ?invoice_payment(?cash(43), ?cash(43), ?bank_card(), <<"2020-02-01T00:00:00Z">>),
{ok, _} = hold_and_commit(?LIMIT_CHANGE(ID, 2), ?payproc_ctx_payment(PaymentFeb), Client),
PaymentApr = ?invoice_payment(?cash(44), ?cash(44), ?bank_card(), <<"2020-04-01T00:00:00Z">>),
{ok, _} = hold_and_commit(?LIMIT_CHANGE(ID, 3), ?payproc_ctx_payment(PaymentApr), Client),
{ok, #limiter_Limit{amount = 42}} = lim_client:get(ID, ?payproc_ctx_payment(PaymentJan), Client),
{ok, #limiter_Limit{amount = 43}} = lim_client:get(ID, ?payproc_ctx_payment(PaymentFeb), Client),
{ok, #limiter_Limit{amount = 44}} = lim_client:get(ID, ?payproc_ctx_payment(PaymentApr), Client).
-spec commit_with_payment_tool_scope_ok(config()) -> _.
commit_with_payment_tool_scope_ok(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?scope([?scope_payment_tool()]), ?turnover_metric_number(), C),
Context1 = ?payproc_ctx_payment(
?invoice_payment(?cash(10), ?cash(10), ?bank_card(<<"Token">>, 2, 2022))
),
Context2 = ?payproc_ctx_payment(
?invoice_payment(?cash(10), ?cash(10), ?bank_card(<<"OtherToken">>, 2, 2022))
),
Context3 = ?payproc_ctx_payment(
?invoice_payment(?cash(10), ?cash(10), ?bank_card(?string, 3, 2022))
),
Context4 = ?payproc_ctx_payment(
?invoice_payment(?cash(10), ?cash(10), ?bank_card(?string))
),
Context5 = ?payproc_ctx_payment(
?invoice_payment(?cash(10), ?cash(10), ?digital_wallet(<<"ID42">>, <<"Pepal">>))
),
{ok, LimitState0} = lim_client:get(ID, Context1, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 1), Context1, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 2), Context2, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 3), Context3, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 4), Context4, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 5), Context5, Client),
{ok, LimitState1} = lim_client:get(ID, Context1, Client),
?assertEqual(
LimitState1#limiter_Limit.amount,
LimitState0#limiter_Limit.amount + 1
).
%%
@ -366,7 +347,7 @@ commit_multirange_limit_ok(C) ->
commit_processes_idempotently(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?global(), C),
Context = ?ctx_invoice_payment(?cash(42), undefined),
Context = ?payproc_ctx_payment(?cash(42), undefined),
Change = ?LIMIT_CHANGE(ID),
{ok, _} = lim_client:hold(Change, Context, Client),
{ok, _} = lim_client:hold(Change, Context, Client),
@ -380,7 +361,7 @@ full_commit_processes_idempotently(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?global(), C),
Cost = ?cash(42),
Context = ?ctx_invoice_payment(Cost, Cost),
Context = ?payproc_ctx_payment(Cost, Cost),
Change = ?LIMIT_CHANGE(ID),
{ok, _} = lim_client:hold(Change, Context, Client),
{ok, _} = lim_client:hold(Change, Context, Client),
@ -393,7 +374,7 @@ full_commit_processes_idempotently(C) ->
partial_commit_processes_idempotently(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?global(), C),
Context = ?ctx_invoice_payment(?cash(42), ?cash(40)),
Context = ?payproc_ctx_payment(?cash(42), ?cash(40)),
Change = ?LIMIT_CHANGE(ID),
{ok, _} = lim_client:hold(Change, Context, Client),
{ok, _} = lim_client:hold(Change, Context, Client),
@ -406,7 +387,7 @@ partial_commit_processes_idempotently(C) ->
rollback_processes_idempotently(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?global(), C),
Context = ?ctx_invoice_payment(?cash(42), ?cash(0)),
Context = ?payproc_ctx_payment(?cash(42), ?cash(0)),
Change = ?LIMIT_CHANGE(ID),
{ok, _} = lim_client:hold(Change, Context, Client),
{ok, _} = lim_client:hold(Change, Context, Client),
@ -421,7 +402,7 @@ rollback_processes_idempotently(C) ->
commit_number_ok(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?global(), ?turnover_metric_number(), C),
Context = ?ctx_invoice_payment(?cash(10), ?cash(10)),
Context = ?payproc_ctx_payment(?cash(10), ?cash(10)),
{ok, LimitState0} = lim_client:get(ID, Context, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID), Context, Client),
{ok, LimitState1} = lim_client:get(ID, Context, Client),
@ -434,8 +415,8 @@ commit_number_ok(C) ->
rollback_number_ok(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?global(), ?turnover_metric_number(), C),
Context = ?ctx_invoice_payment(?cash(10), ?cash(10)),
ContextRollback = ?ctx_invoice_payment(?cash(10), ?cash(0)),
Context = ?payproc_ctx_payment(?cash(10), ?cash(10)),
ContextRollback = ?payproc_ctx_payment(?cash(10), ?cash(0)),
{ok, LimitState0} = lim_client:get(ID, Context, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID), Context, ContextRollback, Client),
{ok, LimitState1} = lim_client:get(ID, Context, Client),
@ -451,8 +432,8 @@ commit_refund_keep_number_unchanged(C) ->
Cost = ?cash(10),
CaptureCost = ?cash(8),
RefundCost = ?cash(5),
PaymentContext = ?ctx_invoice_payment(<<"OWNER">>, <<"SHOP">>, Cost, CaptureCost),
RefundContext = ?ctx_invoice_payment_refund(<<"OWNER">>, <<"SHOP">>, Cost, CaptureCost, RefundCost),
PaymentContext = ?payproc_ctx_payment(<<"OWNER">>, <<"SHOP">>, Cost, CaptureCost),
RefundContext = ?payproc_ctx_refund(<<"OWNER">>, <<"SHOP">>, Cost, CaptureCost, RefundCost),
{ok, LimitState0} = lim_client:get(ID, PaymentContext, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 1), PaymentContext, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 2), RefundContext, Client),
@ -467,8 +448,8 @@ commit_refund_keep_number_unchanged(C) ->
partial_commit_number_counts_as_single_op(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?global(), ?turnover_metric_number(), C),
Context = ?ctx_invoice_payment(?cash(10), ?cash(10)),
ContextPartial = ?ctx_invoice_payment(?cash(10), ?cash(5)),
Context = ?payproc_ctx_payment(?cash(10), ?cash(10)),
ContextPartial = ?payproc_ctx_payment(?cash(10), ?cash(5)),
{ok, LimitState0} = lim_client:get(ID, Context, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID), Context, ContextPartial, Client),
{ok, LimitState1} = lim_client:get(ID, Context, Client),
@ -479,79 +460,6 @@ partial_commit_number_counts_as_single_op(C) ->
%%
-spec payproc_hold_ok(config()) -> _.
payproc_hold_ok(C) ->
ID = configure_limit(?time_range_month(), ?global(), C),
Context = ?payproc_ctx_invoice(?cash(10)),
{ok, {vector, #limiter_VectorClock{}}} = lim_client:hold(?LIMIT_CHANGE(ID), Context, ?config(client, C)),
{ok, #limiter_Limit{}} = lim_client:get(ID, Context, ?config(client, C)).
-spec payproc_commit_ok(config()) -> _.
payproc_commit_ok(C) ->
ID = configure_limit(?time_range_year(), ?global(), C),
Context = ?payproc_ctx_invoice(?cash(10)),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID), Context, ?config(client, C)),
{ok, #limiter_Limit{}} = lim_client:get(ID, Context, ?config(client, C)).
-spec payproc_rollback_ok(config()) -> _.
payproc_rollback_ok(C) ->
ID = configure_limit(?time_range_week(), ?global(), C),
Context0 = ?payproc_ctx_invoice_payment(?cash(10), ?cash(10)),
Context1 = ?payproc_ctx_invoice_payment(?cash(10), ?cash(0)),
Change = ?LIMIT_CHANGE(ID),
{ok, {vector, _}} = lim_client:hold(Change, Context0, ?config(client, C)),
{ok, {vector, _}} = lim_client:commit(Change, Context1, ?config(client, C)).
-spec payproc_refund_ok(config()) -> _.
payproc_refund_ok(C) ->
Client = ?config(client, C),
OwnerID = <<"WWWcool Ltd">>,
ShopID = <<"shop">>,
ID = configure_limit(?time_range_day(), ?scope([?scope_party(), ?scope_shop()]), C),
Context0 = ?payproc_ctx_invoice_payment(OwnerID, ShopID, ?cash(15), ?cash(15)),
RefundContext1 = ?payproc_ctx_invoice_payment_refund(OwnerID, ShopID, ?cash(10), ?cash(10), ?cash(10)),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID, <<"Payment">>), Context0, Client),
{ok, {vector, _}} = hold_and_commit(?LIMIT_CHANGE(ID, <<"Refund">>), RefundContext1, Client),
{ok, #limiter_Limit{} = Limit2} = lim_client:get(ID, RefundContext1, Client),
?assertEqual(Limit2#limiter_Limit.amount, 5).
-spec payproc_commit_with_payment_tool_scope_ok(config()) -> _.
payproc_commit_with_payment_tool_scope_ok(C) ->
Client = ?config(client, C),
ID = configure_limit(?time_range_week(), ?scope([?scope_payment_tool()]), ?turnover_metric_number(), C),
Context0 = ?payproc_ctx_invoice_payment(
?payproc_invoice_payment(
?cash(10),
?cash(10),
{bank_card, ?payproc_bank_card()}
)
),
Context1 = ?payproc_ctx_invoice_payment(
?payproc_invoice_payment(
?cash(10),
?cash(10),
{bank_card, ?payproc_bank_card(<<"OtherToken">>, 2, 2022)}
)
),
Context2 = ?payproc_ctx_invoice_payment(
?payproc_invoice_payment(
?cash(10),
?cash(10),
{bank_card, ?payproc_bank_card(?string, 3, 2022)}
)
),
{ok, LimitState0} = lim_client:get(ID, Context0, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 1), Context0, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 2), Context1, Client),
_ = hold_and_commit(?LIMIT_CHANGE(ID, 3), Context2, Client),
{ok, LimitState1} = lim_client:get(ID, Context0, Client),
?assertEqual(
LimitState1#limiter_Limit.amount,
LimitState0#limiter_Limit.amount + 1
).
%%
gen_change_id(LimitID, ChangeID) ->
genlib:format("~s/~p", [LimitID, ChangeID]).
@ -570,14 +478,19 @@ configure_limit(TimeRange, Scope, C) ->
configure_limit(TimeRange, Scope, Metric, C) ->
ID = ?config(id, C),
Params = #limiter_config_LimitConfigParams{
ContextType =
case get_group_name(C) of
withdrawals -> ?ctx_type_wthdproc();
_Default -> ?ctx_type_payproc()
end,
Params = #config_LimitConfigParams{
id = ID,
started_at = <<"2000-01-01T00:00:00Z">>,
time_range_type = TimeRange,
shard_size = 1,
type = ?lim_type_turnover(Metric),
scope = Scope,
context_type = ?ctx_type_payproc(),
context_type = ContextType,
op_behaviour = ?op_behaviour(?op_subtraction())
},
{ok, _LimitConfig} = lim_client:create_config(Params, ?config(client, C)),
@ -585,3 +498,7 @@ configure_limit(TimeRange, Scope, Metric, C) ->
gen_unique_id(Prefix) ->
genlib:format("~s/~B", [Prefix, lim_time:now()]).
get_group_name(C) ->
GroupProps = ?config(tc_group_properties, C),
proplists:get_value(name, GroupProps).

View File

@ -26,7 +26,6 @@
%% Common project dependencies.
{deps, [
{damsel, {git, "https://github.com/valitydev/damsel.git", {branch, "master"}}},
{limiter_proto, {git, "https://github.com/valitydev/limiter-proto.git", {branch, "master"}}},
{xrates_proto, {git, "https://github.com/valitydev/xrates-proto.git", {branch, "master"}}},
{machinery, {git, "https://github.com/valitydev/machinery-erlang.git", {branch, "master"}}},

View File

@ -9,8 +9,8 @@
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.11.0">>},2},
{<<"damsel">>,
{git,"https://github.com/valitydev/damsel.git",
{ref,"1d60b20f2136938c43902dd38a80ae70f03e4a14"}},
0},
{ref,"33c5665571042440ccec109735481d8c13704ec2"}},
1},
{<<"erl_health">>,
{git,"https://github.com/valitydev/erlang-health.git",
{ref,"5958e2f35cd4d09f40685762b82b82f89b4d9333"}},
@ -25,16 +25,16 @@
{<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},1},
{<<"limiter_proto">>,
{git,"https://github.com/valitydev/limiter-proto.git",
{ref,"ac9705389211682263c0a983ae76f663d4857ec9"}},
{ref,"61581846b4d41de3a9e561c79f558e74450ab950"}},
0},
{<<"machinery">>,
{git,"https://github.com/valitydev/machinery-erlang.git",
{ref,"ff4cfefb616250f6905c25e79f74a7a30eb1aae5"}},
{ref,"62c32434c80a462956ad9d50f9bce47836580d77"}},
0},
{<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},2},
{<<"mg_proto">>,
{git,"https://github.com/valitydev/machinegun-proto.git",
{ref,"b43d6fd0939ee4029ec8873dbd16f3c5fbe4a95c"}},
{ref,"347c5c44c8dcca24a50e0509c0df5401f863e790"}},
1},
{<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},2},
{<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.3.1">>},2},