diff --git a/apps/hellgate/src/hg_invoice_payment.erl b/apps/hellgate/src/hg_invoice_payment.erl index dd97bb50..26874612 100644 --- a/apps/hellgate/src/hg_invoice_payment.erl +++ b/apps/hellgate/src/hg_invoice_payment.erl @@ -2522,6 +2522,7 @@ reject_routes(GroupReason, RejectedRoutes, Ctx) -> get_limit_overflow_routes(Routes, VS, Iter, St) -> Opts = get_opts(St), Revision = get_payment_revision(St), + Session = get_activity_session(St), Payment = get_payment(St), Invoice = get_invoice(Opts), lists:foldl( @@ -2529,7 +2530,7 @@ get_limit_overflow_routes(Routes, VS, Iter, St) -> PaymentRoute = hg_route:to_payment_route(Route), ProviderTerms = hg_routing:get_payment_terms(PaymentRoute, VS, Revision), TurnoverLimits = get_turnover_limits(ProviderTerms, strict), - case hg_limiter:check_limits(TurnoverLimits, Invoice, Payment, PaymentRoute, Iter) of + case hg_limiter:check_limits(TurnoverLimits, Invoice, Payment, Session, PaymentRoute, Iter) of {ok, Limits} -> {[Route | RoutesNoOverflowIn], RejectedIn, LimitsIn#{PaymentRoute => Limits}}; {error, {limit_overflow, IDs, Limits}} -> @@ -2596,6 +2597,7 @@ get_shop_turnover_limits(ShopConfig) -> hold_limit_routes(Routes0, VS, Iter, St) -> Opts = get_opts(St), Revision = get_payment_revision(St), + Session = get_activity_session(St), Payment = get_payment(St), Invoice = get_invoice(Opts), {Routes1, Rejected} = lists:foldl( @@ -2604,7 +2606,7 @@ hold_limit_routes(Routes0, VS, Iter, St) -> ProviderTerms = hg_routing:get_payment_terms(PaymentRoute, VS, Revision), TurnoverLimits = get_turnover_limits(ProviderTerms, strict), try - ok = hg_limiter:hold_payment_limits(TurnoverLimits, Invoice, Payment, PaymentRoute, Iter), + ok = hg_limiter:hold_payment_limits(TurnoverLimits, Invoice, Payment, Session, PaymentRoute, Iter), {[Route | LimitHeldRoutes], RejectedRoutes} catch error:(#limiter_LimitNotFound{} = LimiterError) -> @@ -2630,6 +2632,7 @@ do_reject_route(LimiterError, Route, TurnoverLimits, {LimitHeldRoutes, RejectedR rollback_payment_limits(Routes, Iter, St, Flags) -> Opts = get_opts(St), Revision = get_payment_revision(St), + Session = get_activity_session(St), Payment = get_payment(St), Invoice = get_invoice(Opts), VS = get_varset(St, #{}), @@ -2637,13 +2640,14 @@ rollback_payment_limits(Routes, Iter, St, Flags) -> fun(Route) -> ProviderTerms = hg_routing:get_payment_terms(Route, VS, Revision), TurnoverLimits = get_turnover_limits(ProviderTerms, strict), - ok = hg_limiter:rollback_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, Flags) + ok = hg_limiter:rollback_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, Flags) end, Routes ). rollback_broken_payment_limits(St) -> Opts = get_opts(St), + Session = get_activity_session(St), Payment = get_payment(St), Invoice = get_invoice(Opts), LimitValues = get_limit_values_(St, lenient), @@ -2661,7 +2665,7 @@ rollback_broken_payment_limits(St) -> [], Values ), - ok = hg_limiter:rollback_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, [ + ok = hg_limiter:rollback_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, [ ignore_business_error ]) end, @@ -2681,6 +2685,7 @@ get_turnover_limits(ProviderTerms, Mode) -> commit_payment_limits(#st{capture_data = CaptureData} = St) -> Opts = get_opts(St), Revision = get_payment_revision(St), + Session = get_activity_session(St), Payment = get_payment(St), #payproc_InvoicePaymentCaptureData{cash = CapturedCash} = CaptureData, Invoice = get_invoice(Opts), @@ -2688,7 +2693,7 @@ commit_payment_limits(#st{capture_data = CaptureData} = St) -> ProviderTerms = get_provider_payment_terms(St, Revision), TurnoverLimits = get_turnover_limits(ProviderTerms, strict), Iter = get_iter(St), - hg_limiter:commit_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, CapturedCash). + hg_limiter:commit_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, CapturedCash). commit_payment_cashflow(St) -> Plan = get_cashflow_plan(St), @@ -3482,6 +3487,7 @@ get_limit_values(St, Opts) -> get_limit_values_(St, Mode) -> {PaymentInstitution, VS, Revision} = route_args(St), Ctx = build_routing_context(PaymentInstitution, VS, Revision, St), + Session = get_activity_session(St), Payment = get_payment(St), Invoice = get_invoice(get_opts(St)), %% NOTE If event 'route_changed' didn't occur, then there may be @@ -3498,7 +3504,7 @@ get_limit_values_(St, Mode) -> ProviderTerms = hg_routing:get_payment_terms(PaymentRoute, VS, Revision), TurnoverLimits = get_turnover_limits(ProviderTerms, Mode), TurnoverLimitValues = - hg_limiter:get_limit_values(TurnoverLimits, Invoice, Payment, PaymentRoute, Iter), + hg_limiter:get_limit_values(TurnoverLimits, Invoice, Payment, Session, PaymentRoute, Iter), Acc#{PaymentRoute => TurnoverLimitValues} end, #{}, @@ -3633,7 +3639,9 @@ get_payment_state(InvoiceID, PaymentID) -> throw(#payproc_InvoicePaymentNotFound{}) end. --spec get_session(target(), st()) -> session(). +-spec get_session(target(), st()) -> session() | undefined. +get_session(_Target, #st{routes = []}) -> + undefined; get_session(Target, #st{sessions = Sessions, routes = [Route | _PreviousRoutes]}) -> TargetSessions = maps:get(get_target_type(Target), Sessions, []), MatchingRoute = fun(#{route := SR}) -> SR =:= Route end, @@ -3679,7 +3687,9 @@ get_activity_session({payment, _Step}, St) -> get_session(get_target(St), St); get_activity_session({refund, ID}, St) -> Refund = try_get_refund_state(ID, St), - hg_invoice_payment_refund:session(Refund). + hg_invoice_payment_refund:session(Refund); +get_activity_session(_, _St) -> + undefined. %% diff --git a/apps/hellgate/src/hg_invoice_registered_payment.erl b/apps/hellgate/src/hg_invoice_registered_payment.erl index ec68df5d..59e4c3af 100644 --- a/apps/hellgate/src/hg_invoice_registered_payment.erl +++ b/apps/hellgate/src/hg_invoice_registered_payment.erl @@ -198,7 +198,7 @@ hold_payment_limits(Invoice, Payment, St) -> Route = hg_invoice_payment:get_route(St), TurnoverLimits = get_turnover_limits(Payment, Route, St), Iter = hg_invoice_payment:get_iter(St), - hg_limiter:hold_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter). + hg_limiter:hold_payment_limits(TurnoverLimits, Invoice, Payment, undefined, Route, Iter). get_turnover_limits(Payment, Route, St) -> Route = hg_invoice_payment:get_route(St), diff --git a/apps/hellgate/src/hg_limiter.erl b/apps/hellgate/src/hg_limiter.erl index e448861f..17a18b2b 100644 --- a/apps/hellgate/src/hg_limiter.erl +++ b/apps/hellgate/src/hg_limiter.erl @@ -10,6 +10,7 @@ -type turnover_limit() :: dmsl_domain_thrift:'TurnoverLimit'(). -type invoice() :: dmsl_domain_thrift:'Invoice'(). -type payment() :: dmsl_domain_thrift:'InvoicePayment'(). +-type session() :: hg_session:t(). -type route() :: hg_route:payment_route(). -type refund() :: hg_invoice_payment:domain_refund(). -type cash() :: dmsl_domain_thrift:'Cash'(). @@ -21,18 +22,18 @@ -export_type([turnover_limit_value/0]). -export([get_turnover_limits/2]). --export([check_limits/5]). +-export([check_limits/6]). -export([check_shop_limits/5]). --export([hold_payment_limits/5]). +-export([hold_payment_limits/6]). -export([hold_shop_limits/5]). -export([hold_refund_limits/5]). --export([commit_payment_limits/6]). +-export([commit_payment_limits/7]). -export([commit_shop_limits/5]). -export([commit_refund_limits/5]). --export([rollback_payment_limits/6]). +-export([rollback_payment_limits/7]). -export([rollback_shop_limits/6]). -export([rollback_refund_limits/5]). --export([get_limit_values/5]). +-export([get_limit_values/6]). -define(route(ProviderRef, TerminalRef), #domain_PaymentRoute{ provider = ProviderRef, @@ -77,9 +78,10 @@ filter_existing_turnover_limits(Limits, Mode) -> Limits ). --spec get_limit_values([turnover_limit()], invoice(), payment(), route(), pos_integer()) -> [turnover_limit_value()]. -get_limit_values(TurnoverLimits, Invoice, Payment, Route, Iter) -> - Context = gen_limit_context(Invoice, Payment, Route), +-spec get_limit_values([turnover_limit()], invoice(), payment(), session() | undefined, route(), pos_integer()) -> + [turnover_limit_value()]. +get_limit_values(TurnoverLimits, Invoice, Payment, Session, Route, Iter) -> + Context = gen_limit_context(Invoice, Payment, Session, Route), get_limit_values(Context, TurnoverLimits, make_route_operation_segments(Invoice, Payment, Route, Iter)). make_route_operation_segments(Invoice, Payment, ?route(ProviderRef, TerminalRef), Iter) -> @@ -105,11 +107,11 @@ get_batch_limit_values(Context, TurnoverLimits, OperationIdSegments) -> hg_limiter_client:get_batch(LimitRequest, Context) ). --spec check_limits([turnover_limit()], invoice(), payment(), route(), pos_integer()) -> +-spec check_limits([turnover_limit()], invoice(), payment(), session() | undefined, route(), pos_integer()) -> {ok, [turnover_limit_value()]} | {error, {limit_overflow, [binary()], [turnover_limit_value()]}}. -check_limits(TurnoverLimits, Invoice, Payment, Route, Iter) -> - Context = gen_limit_context(Invoice, Payment, Route), +check_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter) -> + Context = gen_limit_context(Invoice, Payment, Session, Route), Limits = get_limit_values(Context, TurnoverLimits, make_route_operation_segments(Invoice, Payment, Route, Iter)), try ok = check_limits_(Limits, Context), @@ -166,9 +168,10 @@ check_limits_([TurnoverLimitValue | TLVs], Context) -> throw(limit_overflow) end. --spec hold_payment_limits([turnover_limit()], invoice(), payment(), route(), pos_integer()) -> ok. -hold_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter) -> - Context = gen_limit_context(Invoice, Payment, Route), +-spec hold_payment_limits([turnover_limit()], invoice(), payment(), session() | undefined, route(), pos_integer()) -> + ok. +hold_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter) -> + Context = gen_limit_context(Invoice, Payment, Session, Route), ok = batch_hold_limits(Context, TurnoverLimits, make_route_operation_segments(Invoice, Payment, Route, Iter)). batch_hold_limits(_Context, [], _OperationIdSegments) -> @@ -197,9 +200,17 @@ make_refund_operation_segments(Invoice, Payment, Refund) -> {refund_session, get_refund_id(Refund)} ]. --spec commit_payment_limits([turnover_limit()], invoice(), payment(), route(), pos_integer(), cash() | undefined) -> ok. -commit_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, CapturedCash) -> - Context = gen_limit_context(Invoice, Payment, Route, CapturedCash), +-spec commit_payment_limits( + [turnover_limit()], + invoice(), + payment(), + session() | undefined, + route(), + pos_integer(), + cash() | undefined +) -> ok. +commit_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, CapturedCash) -> + Context = gen_limit_context(Invoice, Payment, Session, Route, CapturedCash), OperationIdSegments = make_route_operation_segments(Invoice, Payment, Route, Iter), ok = batch_commit_limits(Context, TurnoverLimits, OperationIdSegments). @@ -243,10 +254,18 @@ batch_commit_limits(Context, TurnoverLimits, OperationIdSegments) -> %% %% - `ignore_not_found` -- does not raise error if limiter won't be able to %% find according posting plan in accountant service --spec rollback_payment_limits([turnover_limit()], invoice(), payment(), route(), pos_integer(), [handling_flag()]) -> +-spec rollback_payment_limits( + [turnover_limit()], + invoice(), + payment(), + session() | undefined, + route(), + pos_integer(), + [handling_flag()] +) -> ok. -rollback_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, Flags) -> - Context = gen_limit_context(Invoice, Payment, Route), +rollback_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, Flags) -> + Context = gen_limit_context(Invoice, Payment, Session, Route), OperationIdSegments = make_route_operation_segments(Invoice, Payment, Route, Iter), ok = batch_rollback_limits(Context, TurnoverLimits, OperationIdSegments, Flags). @@ -281,10 +300,10 @@ rollback_refund_limits(TurnoverLimits, Invoice, Payment, Refund, Route) -> OperationIdSegments = make_refund_operation_segments(Invoice, Payment, Refund), ok = batch_rollback_limits(Context, TurnoverLimits, OperationIdSegments, []). -gen_limit_context(Invoice, Payment, Route) -> - gen_limit_context(Invoice, Payment, Route, undefined). +gen_limit_context(Invoice, Payment, Session, Route) -> + gen_limit_context(Invoice, Payment, Session, Route, undefined). -gen_limit_context(Invoice, Payment, Route, CapturedCash) -> +gen_limit_context(Invoice, Payment, Session, Route, CapturedCash) -> PaymentCtx = #context_payproc_InvoicePayment{ payment = Payment#domain_InvoicePayment{ status = {captured, #domain_InvoicePaymentCaptured{cost = CapturedCash}} @@ -296,11 +315,17 @@ gen_limit_context(Invoice, Payment, Route, CapturedCash) -> op = {invoice_payment, #context_payproc_OperationInvoicePayment{}}, invoice = #context_payproc_Invoice{ invoice = Invoice, - payment = PaymentCtx + payment = PaymentCtx, + session = gen_limit_session_context(Session, Route) } } }. +gen_limit_session_context(#{status := finished, route := Route}, Route) -> + #context_payproc_InvoicePaymentSession{}; +gen_limit_session_context(_, _) -> + undefined. + gen_limit_shop_context(Invoice, Payment) -> #limiter_LimitContext{ payment_processing = #context_payproc_Context{ diff --git a/apps/hellgate/test/hg_invoice_tests_SUITE.erl b/apps/hellgate/test/hg_invoice_tests_SUITE.erl index c0ff2506..fbcf5643 100644 --- a/apps/hellgate/test/hg_invoice_tests_SUITE.erl +++ b/apps/hellgate/test/hg_invoice_tests_SUITE.erl @@ -235,6 +235,7 @@ init([]) -> -define(LIMIT_ID3, <<"ID3">>). -define(LIMIT_ID4, <<"ID4">>). -define(SHOPLIMIT_ID, <<"SHOPLIMITID">>). +-define(LIMIT_TERMINAL_FAILURES, <<"TERMINAL_FAILURES">>). -define(LIMIT_UPPER_BOUNDARY, 100000). -define(BIG_LIMIT_UPPER_BOUNDARY, 1000000). -define(DEFAULT_NEXT_CHANGE_TIMEOUT, 12000). @@ -724,7 +725,7 @@ init_per_testcase(repair_fail_routing_succeeded = Name, C) -> meck:expect( hg_limiter, check_limits, - fun override_check_limits/5 + fun override_check_limits/6 ), init_per_testcase_(Name, C); init_per_testcase(repair_fail_cash_flow_building_succeeded = Name, C) -> @@ -745,8 +746,8 @@ init_per_testcase(Name, C) -> end, init_per_testcase_(Name, C1). -override_check_limits(_, _, _, _, _) -> throw(unknown). --dialyzer({nowarn_function, override_check_limits/5}). +override_check_limits(_, _, _, _, _, _) -> throw(unknown). +-dialyzer({nowarn_function, override_check_limits/6}). override_collect_cashflow(_) -> throw(unknown). -dialyzer({nowarn_function, override_collect_cashflow/1}). @@ -1353,7 +1354,7 @@ payment_limit_overflow(C) -> Failure = create_payment_limit_overflow(PartyConfigRef, ShopConfigRef, 1000, Client, PmtSys), ok = hg_limiter_helper:assert_payment_limit_amount( - ?LIMIT_ID, configured_limit_version(?LIMIT_ID, C), PaymentAmount, Payment, Invoice + ?LIMIT_ID, configured_limit_version(C), PaymentAmount, Payment, Invoice ), ok = payproc_errors:match( 'PaymentFailure', @@ -1423,7 +1424,7 @@ switch_provider_after_limit_overflow(C) -> ) = create_payment(PartyConfigRef, ShopConfigRef, PaymentAmount, Client, PmtSys), ok = hg_limiter_helper:assert_payment_limit_amount( - ?LIMIT_ID, configured_limit_version(?LIMIT_ID, C), PaymentAmount, Payment, Invoice + ?LIMIT_ID, configured_limit_version(C), PaymentAmount, Payment, Invoice ), #domain_InvoicePayment{id = PaymentID} = Payment, @@ -6389,12 +6390,9 @@ payment_cascade_success(C) -> }, #payproc_InvoicePayment{payment = Payment} = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client), ?invoice_created(?invoice_w_status(?invoice_unpaid())) = next_change(InvoiceID, Client), - Limit = hg_limiter_helper:maybe_uninitialized_limit( - hg_limiter_helper:get_payment_limit_amount( - ?LIMIT_ID4, configured_limit_version(?LIMIT_ID4, C), Payment, Invoice - ) + InitialAccountedAmount = hg_limiter_helper:get_amount( + ?LIMIT_ID4, configured_limit_version(C), Payment, Invoice, undefined ), - InitialAccountedAmount = hg_limiter_helper:get_amount(Limit), [ ?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))), ?payment_ev(PaymentID, ?shop_limit_initiated()), @@ -6448,7 +6446,7 @@ payment_cascade_success(C) -> ), %% At the end of this scenario limit must be accounted only once. _ = hg_limiter_helper:assert_payment_limit_amount( - ?LIMIT_ID4, configured_limit_version(?LIMIT_ID4, C), InitialAccountedAmount + Amount, PaymentFinal, Invoice + ?LIMIT_ID4, configured_limit_version(C), InitialAccountedAmount + Amount, PaymentFinal, Invoice ), #payproc_InvoicePaymentExplanation{ explained_routes = [ @@ -6564,6 +6562,11 @@ payment_big_cascade_success_fixture(Revision, _C) -> ref = ?lim(?LIMIT_ID4), upper_boundary = ?BIG_LIMIT_UPPER_BOUNDARY, domain_revision = Revision + }, + #domain_TurnoverLimit{ + ref = ?lim(?LIMIT_TERMINAL_FAILURES), + upper_boundary = ?BIG_LIMIT_UPPER_BOUNDARY, + domain_revision = Revision } ]} } @@ -6777,12 +6780,9 @@ payment_cascade_limit_overflow(C) -> }, #payproc_InvoicePayment{payment = Payment} = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client), ?invoice_created(?invoice_w_status(?invoice_unpaid())) = next_change(InvoiceID, Client), - Limit = hg_limiter_helper:maybe_uninitialized_limit( - hg_limiter_helper:get_payment_limit_amount( - ?LIMIT_ID4, configured_limit_version(?LIMIT_ID4, C), Payment, Invoice - ) + InitialAccountedAmount = hg_limiter_helper:get_amount( + ?LIMIT_ID4, configured_limit_version(C), Payment, Invoice, undefined ), - InitialAccountedAmount = hg_limiter_helper:get_amount(Limit), [ ?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))), ?payment_ev(PaymentID, ?shop_limit_initiated()), @@ -6810,7 +6810,7 @@ payment_cascade_limit_overflow(C) -> ?invoice_status_changed(?invoice_cancelled(<<"overdue">>)) = next_change(InvoiceID, Client), %% At the end of this scenario limit must not be changed. hg_limiter_helper:assert_payment_limit_amount( - ?LIMIT_ID4, configured_limit_version(?LIMIT_ID4, C), InitialAccountedAmount, FinalPayment, Invoice + ?LIMIT_ID4, configured_limit_version(C), InitialAccountedAmount, FinalPayment, Invoice ). -spec payment_big_cascade_success(config()) -> test_return(). @@ -6839,12 +6839,9 @@ payment_big_cascade_success(C) -> }, #payproc_InvoicePayment{payment = Payment} = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client), ?invoice_created(?invoice_w_status(?invoice_unpaid())) = next_change(InvoiceID, Client), - Limit = hg_limiter_helper:maybe_uninitialized_limit( - hg_limiter_helper:get_payment_limit_amount( - ?LIMIT_ID4, configured_limit_version(?LIMIT_ID4, C), Payment, Invoice - ) + InitialAccountedAmount = hg_limiter_helper:get_amount( + ?LIMIT_ID4, configured_limit_version(C), Payment, Invoice, undefined ), - InitialAccountedAmount = hg_limiter_helper:get_amount(Limit), [ ?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))), ?payment_ev(PaymentID, ?shop_limit_initiated()), @@ -6853,13 +6850,20 @@ payment_big_cascade_success(C) -> ] = next_changes(InvoiceID, 4, Client), [ (fun() -> - {_Route, _CashFlow, _TrxID, Failure} = + {Route, _CashFlow, _TrxID, Failure} = await_cascade_triggering(InvoiceID, PaymentID, Client), ok = payproc_errors:match( 'PaymentFailure', Failure, fun({preauthorization_failed, {card_blocked, _}}) -> ok end ), + ?assertNotEqual( + 0, + hg_limiter_helper:get_amount( + ?LIMIT_TERMINAL_FAILURES, configured_limit_version(C), Payment, Invoice, Route + ), + "Session failure must be accounted for attempted route on rollback" + ), %% Assert payment status IS NOT failed ?invoice_state(?invoice_w_status(_), [?payment_state(PaymentInterim)]) = hg_client_invoicing:get(InvoiceID, Client), @@ -6901,7 +6905,18 @@ payment_big_cascade_success(C) -> ), %% At the end of this scenario limit must be accounted only once. hg_limiter_helper:assert_payment_limit_amount( - ?LIMIT_ID4, configured_limit_version(?LIMIT_ID4, C), InitialAccountedAmount + Amount, PaymentFinal, Invoice + ?LIMIT_ID4, configured_limit_version(C), InitialAccountedAmount + Amount, PaymentFinal, Invoice + ), + ?assertEqual( + 0, + hg_limiter_helper:get_amount( + ?LIMIT_TERMINAL_FAILURES, + configured_limit_version(C), + PaymentFinal, + Invoice, + RouteFinal + ), + "Successful payment session must not count against failures counter" ). payment_cascade_fail_provider_error_fixture_pre(Revision, _C) -> @@ -10649,5 +10664,5 @@ mock_fault_detector(SupPid) -> SupPid ). -configured_limit_version(_LimitID, C) -> +configured_limit_version(C) -> genlib:define(cfg(original_domain_revision, C), cfg(base_limits_domain_revision, C)). diff --git a/apps/hellgate/test/hg_limiter_helper.erl b/apps/hellgate/test/hg_limiter_helper.erl index ae80109a..9d392614 100644 --- a/apps/hellgate/test/hg_limiter_helper.erl +++ b/apps/hellgate/test/hg_limiter_helper.erl @@ -1,5 +1,6 @@ -module(hg_limiter_helper). +-include_lib("limiter_proto/include/limproto_base_thrift.hrl"). -include_lib("limiter_proto/include/limproto_limiter_thrift.hrl"). -include_lib("limiter_proto/include/limproto_context_payproc_thrift.hrl"). -include_lib("damsel/include/dmsl_domain_thrift.hrl"). @@ -8,8 +9,9 @@ -include_lib("stdlib/include/assert.hrl"). -export([init_per_suite/1]). --export([get_amount/1]). +-export([get_amount/5]). -export([assert_payment_limit_amount/5]). +-export([assert_payment_limit_amount/6]). -export([maybe_uninitialized_limit/1]). -export([get_payment_limit_amount/4]). -export([mk_config_object/2, mk_config_object/3, mk_config_object/4]). @@ -23,6 +25,7 @@ -define(LIMIT_ID3, <<"ID3">>). -define(LIMIT_ID4, <<"ID4">>). -define(SHOPLIMIT_ID, <<"SHOPLIMITID">>). +-define(LIMIT_TERMINAL_FAILURES, <<"TERMINAL_FAILURES">>). -define(PLACEHOLDER_UNINITIALIZED_LIMIT_ID, <<"uninitialized limit">>). -define(PLACEHOLDER_OPERATION_GET_LIMIT_VALUES, <<"get values">>). @@ -36,19 +39,33 @@ init_per_suite(_Config) -> {limit_config, mk_config_object(?LIMIT_ID2)}, {limit_config, mk_config_object(?LIMIT_ID3)}, {limit_config, mk_config_object(?LIMIT_ID4)}, - {limit_config, mk_config_object(?SHOPLIMIT_ID)} + {limit_config, mk_config_object(?SHOPLIMIT_ID)}, + {limit_config, + mk_config_object( + ?LIMIT_TERMINAL_FAILURES, + <<"RUB">>, + mk_context_type(payment), + mk_scopes([payment_tool, terminal]), + mk_fin_behaviour(invertable) + )} ], dmt_client:create_author(genlib:unique(), genlib:unique()), #{} ). --spec get_amount(_) -> pos_integer(). -get_amount(#limiter_Limit{amount = Amount}) -> - Amount. +-spec get_amount(_, _, _, _, _) -> pos_integer(). +get_amount(LimitID, Version, Payment, Invoice, Route) -> + Result = get_payment_limit_amount(LimitID, Version, Payment, Invoice, Route), + Limit = maybe_uninitialized_limit(Result), + Limit#limiter_Limit.amount. -spec assert_payment_limit_amount(_, _, _, _, _) -> _. assert_payment_limit_amount(LimitID, Version, AssertAmount, Payment, Invoice) -> - Result = get_payment_limit_amount(LimitID, Version, Payment, Invoice), + assert_payment_limit_amount(LimitID, Version, AssertAmount, Payment, Invoice, undefined). + +-spec assert_payment_limit_amount(_, _, _, _, _, _) -> _. +assert_payment_limit_amount(LimitID, Version, AssertAmount, Payment, Invoice, Route) -> + Result = get_payment_limit_amount(LimitID, Version, Payment, Invoice, Route), Limit = maybe_uninitialized_limit(Result), #limiter_Limit{amount = CurrentAmount} = Limit, ?assertEqual(AssertAmount, CurrentAmount, {LimitID, Result}). @@ -66,13 +83,24 @@ maybe_uninitialized_limit({exception, _}) -> -spec get_payment_limit_amount(_, _, _, _) -> _. get_payment_limit_amount(LimitID, Version, Payment, Invoice) -> + get_payment_limit_amount(LimitID, Version, Payment, Invoice, undefined). + +-spec get_payment_limit_amount(_, _, _, _, _) -> _. +get_payment_limit_amount(LimitID, Version, Payment, Invoice, Route) -> Context = #limiter_LimitContext{ payment_processing = #context_payproc_Context{ op = {invoice_payment, #context_payproc_OperationInvoicePayment{}}, invoice = #context_payproc_Invoice{ invoice = Invoice, payment = #context_payproc_InvoicePayment{ - payment = Payment + payment = Payment, + route = + case Route of + undefined -> + undefined; + #domain_PaymentRoute{provider = Provider, terminal = Terminal} -> + #base_Route{provider = Provider, terminal = Terminal} + end } } } @@ -104,6 +132,10 @@ mk_config_object(LimitID, Currency, ContextType) -> -spec mk_config_object(_, _, _, _) -> _. mk_config_object(LimitID, Currency, ContextType, Scopes) -> + mk_config_object(LimitID, Currency, ContextType, Scopes, mk_fin_behaviour(normal)). + +-spec mk_config_object(_, _, _, _, _) -> _. +mk_config_object(LimitID, Currency, ContextType, Scopes, FinalizationBehaviour) -> #domain_LimitConfigObject{ ref = #domain_LimitConfigRef{id = LimitID}, data = #limiter_config_LimitConfig{ @@ -120,7 +152,8 @@ mk_config_object(LimitID, Currency, ContextType, Scopes) -> description = <<"description">>, op_behaviour = #limiter_config_OperationLimitBehaviour{ invoice_payment_refund = {subtraction, #limiter_config_Subtraction{}} - } + }, + finalization_behaviour = FinalizationBehaviour } }. @@ -133,3 +166,8 @@ mk_context_type(payment) -> -spec mk_scopes(_) -> _. mk_scopes(ScopeTags) -> ordsets:from_list([{Tag, #limiter_config_LimitScopeEmptyDetails{}} || Tag <- ScopeTags]). + +mk_fin_behaviour(normal) -> + {normal, #limiter_config_Normal{}}; +mk_fin_behaviour(invertable) -> + {invertable, {session_presence, #limiter_config_Inversed{}}}. diff --git a/compose.yaml b/compose.yaml index 142d2e6e..2b936ce3 100644 --- a/compose.yaml +++ b/compose.yaml @@ -27,7 +27,7 @@ services: command: /sbin/init dmt: - image: ghcr.io/valitydev/dominant-v2:sha-3ad3a22 + image: ghcr.io/valitydev/dominant-v2:sha-815385c command: /opt/dmt/bin/dmt foreground volumes: - ./test/dmt/sys.config:/opt/dmt/releases/0.1/sys.config @@ -55,7 +55,7 @@ services: retries: 10 limiter: - image: ghcr.io/valitydev/limiter:sha-2a3f78d + image: ghcr.io/valitydev/limiter:sha-67cf0b7 command: /opt/limiter/bin/limiter foreground depends_on: liminator: diff --git a/rebar.config b/rebar.config index e54b9e06..767b1932 100644 --- a/rebar.config +++ b/rebar.config @@ -31,7 +31,7 @@ {gproc, "0.9.0"}, {genlib, {git, "https://github.com/valitydev/genlib.git", {tag, "v1.1.0"}}}, {woody, {git, "https://github.com/valitydev/woody_erlang.git", {tag, "v1.1.1"}}}, - {damsel, {git, "https://github.com/valitydev/damsel.git", {tag, "v2.2.23"}}}, + {damsel, {git, "https://github.com/valitydev/damsel.git", {tag, "v2.2.27"}}}, {payproc_errors, {git, "https://github.com/valitydev/payproc-errors-erlang.git", {branch, "master"}}}, {mg_proto, {git, "https://github.com/valitydev/machinegun-proto.git", {branch, "master"}}}, {dmt_client, {git, "https://github.com/valitydev/dmt-client.git", {tag, "v2.0.3"}}}, @@ -40,7 +40,7 @@ {bender_client, {git, "https://github.com/valitydev/bender-client-erlang.git", {tag, "v1.1.0"}}}, {erl_health, {git, "https://github.com/valitydev/erlang-health.git", {tag, "v1.0.0"}}}, {fault_detector_proto, {git, "https://github.com/valitydev/fault-detector-proto.git", {branch, "master"}}}, - {limiter_proto, {git, "https://github.com/valitydev/limiter-proto.git", {tag, "v2.1.0"}}}, + {limiter_proto, {git, "https://github.com/valitydev/limiter-proto.git", {tag, "v2.1.1"}}}, {herd, {git, "https://github.com/wgnet/herd.git", {tag, "1.3.4"}}}, {progressor, {git, "https://github.com/valitydev/progressor.git", {tag, "v1.0.20"}}}, {prometheus, "4.11.0"}, diff --git a/rebar.lock b/rebar.lock index 11e04791..b1c856d5 100644 --- a/rebar.lock +++ b/rebar.lock @@ -27,7 +27,7 @@ {<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},2}, {<<"damsel">>, {git,"https://github.com/valitydev/damsel.git", - {ref,"b5c1dc423365397d8c2d123ba5766147551f19cc"}}, + {ref,"074ba8c024af7902ead5f24dc3d288c1922651c1"}}, 0}, {<<"dmt_client">>, {git,"https://github.com/valitydev/dmt-client.git", @@ -72,7 +72,7 @@ {<<"kafka_protocol">>,{pkg,<<"kafka_protocol">>,<<"4.1.10">>},2}, {<<"limiter_proto">>, {git,"https://github.com/valitydev/limiter-proto.git", - {ref,"1af3724af24dd8b5ad9ce2ae80cd42318b471397"}}, + {ref,"ced168a6ea11f80d62485b793b3605de68223e38"}}, 0}, {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},2}, {<<"mg_proto">>,