Skip to content

Commit cec8ef0

Browse files
authored
BG-753: Implements limit context's payment session support (#195)
* BG-753: Implements limit context's payment session support * Cleans up auto formatting * Fixes getting session from overall state * Fixes missing route for session in limit context * Updates 'big cascade' testcase w/ invertable limit * Adds routing candidate limit's assertions for terminal's failures
1 parent 23dc87e commit cec8ef0

9 files changed

Lines changed: 189 additions & 84 deletions

apps/hellgate/include/payment_events.hrl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
55
-include_lib("damsel/include/dmsl_user_interaction_thrift.hrl").
66
-include_lib("damsel/include/dmsl_payproc_thrift.hrl").
7+
-include_lib("hellgate/include/payment_events.hrl").
78

89
%% Payments
910

apps/hellgate/src/hg_invoice_payment.erl

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,14 +2522,15 @@ reject_routes(GroupReason, RejectedRoutes, Ctx) ->
25222522
get_limit_overflow_routes(Routes, VS, Iter, St) ->
25232523
Opts = get_opts(St),
25242524
Revision = get_payment_revision(St),
2525+
Session = get_activity_session(St),
25252526
Payment = get_payment(St),
25262527
Invoice = get_invoice(Opts),
25272528
lists:foldl(
25282529
fun(Route, {RoutesNoOverflowIn, RejectedIn, LimitsIn}) ->
25292530
PaymentRoute = hg_route:to_payment_route(Route),
25302531
ProviderTerms = hg_routing:get_payment_terms(PaymentRoute, VS, Revision),
25312532
TurnoverLimits = get_turnover_limits(ProviderTerms, strict),
2532-
case hg_limiter:check_limits(TurnoverLimits, Invoice, Payment, PaymentRoute, Iter) of
2533+
case hg_limiter:check_limits(TurnoverLimits, Invoice, Payment, Session, PaymentRoute, Iter) of
25332534
{ok, Limits} ->
25342535
{[Route | RoutesNoOverflowIn], RejectedIn, LimitsIn#{PaymentRoute => Limits}};
25352536
{error, {limit_overflow, IDs, Limits}} ->
@@ -2596,6 +2597,7 @@ get_shop_turnover_limits(ShopConfig) ->
25962597
hold_limit_routes(Routes0, VS, Iter, St) ->
25972598
Opts = get_opts(St),
25982599
Revision = get_payment_revision(St),
2600+
Session = get_activity_session(St),
25992601
Payment = get_payment(St),
26002602
Invoice = get_invoice(Opts),
26012603
{Routes1, Rejected} = lists:foldl(
@@ -2604,7 +2606,7 @@ hold_limit_routes(Routes0, VS, Iter, St) ->
26042606
ProviderTerms = hg_routing:get_payment_terms(PaymentRoute, VS, Revision),
26052607
TurnoverLimits = get_turnover_limits(ProviderTerms, strict),
26062608
try
2607-
ok = hg_limiter:hold_payment_limits(TurnoverLimits, Invoice, Payment, PaymentRoute, Iter),
2609+
ok = hg_limiter:hold_payment_limits(TurnoverLimits, Invoice, Payment, Session, PaymentRoute, Iter),
26082610
{[Route | LimitHeldRoutes], RejectedRoutes}
26092611
catch
26102612
error:(#limiter_LimitNotFound{} = LimiterError) ->
@@ -2630,20 +2632,22 @@ do_reject_route(LimiterError, Route, TurnoverLimits, {LimitHeldRoutes, RejectedR
26302632
rollback_payment_limits(Routes, Iter, St, Flags) ->
26312633
Opts = get_opts(St),
26322634
Revision = get_payment_revision(St),
2635+
Session = get_activity_session(St),
26332636
Payment = get_payment(St),
26342637
Invoice = get_invoice(Opts),
26352638
VS = get_varset(St, #{}),
26362639
lists:foreach(
26372640
fun(Route) ->
26382641
ProviderTerms = hg_routing:get_payment_terms(Route, VS, Revision),
26392642
TurnoverLimits = get_turnover_limits(ProviderTerms, strict),
2640-
ok = hg_limiter:rollback_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, Flags)
2643+
ok = hg_limiter:rollback_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, Flags)
26412644
end,
26422645
Routes
26432646
).
26442647

26452648
rollback_broken_payment_limits(St) ->
26462649
Opts = get_opts(St),
2650+
Session = get_activity_session(St),
26472651
Payment = get_payment(St),
26482652
Invoice = get_invoice(Opts),
26492653
LimitValues = get_limit_values_(St, lenient),
@@ -2661,7 +2665,7 @@ rollback_broken_payment_limits(St) ->
26612665
[],
26622666
Values
26632667
),
2664-
ok = hg_limiter:rollback_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, [
2668+
ok = hg_limiter:rollback_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, [
26652669
ignore_business_error
26662670
])
26672671
end,
@@ -2681,14 +2685,15 @@ get_turnover_limits(ProviderTerms, Mode) ->
26812685
commit_payment_limits(#st{capture_data = CaptureData} = St) ->
26822686
Opts = get_opts(St),
26832687
Revision = get_payment_revision(St),
2688+
Session = get_activity_session(St),
26842689
Payment = get_payment(St),
26852690
#payproc_InvoicePaymentCaptureData{cash = CapturedCash} = CaptureData,
26862691
Invoice = get_invoice(Opts),
26872692
Route = get_route(St),
26882693
ProviderTerms = get_provider_payment_terms(St, Revision),
26892694
TurnoverLimits = get_turnover_limits(ProviderTerms, strict),
26902695
Iter = get_iter(St),
2691-
hg_limiter:commit_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, CapturedCash).
2696+
hg_limiter:commit_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, CapturedCash).
26922697

26932698
commit_payment_cashflow(St) ->
26942699
Plan = get_cashflow_plan(St),
@@ -3482,6 +3487,7 @@ get_limit_values(St, Opts) ->
34823487
get_limit_values_(St, Mode) ->
34833488
{PaymentInstitution, VS, Revision} = route_args(St),
34843489
Ctx = build_routing_context(PaymentInstitution, VS, Revision, St),
3490+
Session = get_activity_session(St),
34853491
Payment = get_payment(St),
34863492
Invoice = get_invoice(get_opts(St)),
34873493
%% NOTE If event 'route_changed' didn't occur, then there may be
@@ -3498,7 +3504,7 @@ get_limit_values_(St, Mode) ->
34983504
ProviderTerms = hg_routing:get_payment_terms(PaymentRoute, VS, Revision),
34993505
TurnoverLimits = get_turnover_limits(ProviderTerms, Mode),
35003506
TurnoverLimitValues =
3501-
hg_limiter:get_limit_values(TurnoverLimits, Invoice, Payment, PaymentRoute, Iter),
3507+
hg_limiter:get_limit_values(TurnoverLimits, Invoice, Payment, Session, PaymentRoute, Iter),
35023508
Acc#{PaymentRoute => TurnoverLimitValues}
35033509
end,
35043510
#{},
@@ -3633,7 +3639,9 @@ get_payment_state(InvoiceID, PaymentID) ->
36333639
throw(#payproc_InvoicePaymentNotFound{})
36343640
end.
36353641

3636-
-spec get_session(target(), st()) -> session().
3642+
-spec get_session(target(), st()) -> session() | undefined.
3643+
get_session(_Target, #st{routes = []}) ->
3644+
undefined;
36373645
get_session(Target, #st{sessions = Sessions, routes = [Route | _PreviousRoutes]}) ->
36383646
TargetSessions = maps:get(get_target_type(Target), Sessions, []),
36393647
MatchingRoute = fun(#{route := SR}) -> SR =:= Route end,
@@ -3679,7 +3687,9 @@ get_activity_session({payment, _Step}, St) ->
36793687
get_session(get_target(St), St);
36803688
get_activity_session({refund, ID}, St) ->
36813689
Refund = try_get_refund_state(ID, St),
3682-
hg_invoice_payment_refund:session(Refund).
3690+
hg_invoice_payment_refund:session(Refund);
3691+
get_activity_session(_, _St) ->
3692+
undefined.
36833693

36843694
%%
36853695

apps/hellgate/src/hg_invoice_registered_payment.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ hold_payment_limits(Invoice, Payment, St) ->
198198
Route = hg_invoice_payment:get_route(St),
199199
TurnoverLimits = get_turnover_limits(Payment, Route, St),
200200
Iter = hg_invoice_payment:get_iter(St),
201-
hg_limiter:hold_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter).
201+
hg_limiter:hold_payment_limits(TurnoverLimits, Invoice, Payment, undefined, Route, Iter).
202202

203203
get_turnover_limits(Payment, Route, St) ->
204204
Route = hg_invoice_payment:get_route(St),

apps/hellgate/src/hg_limiter.erl

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
-type turnover_limit() :: dmsl_domain_thrift:'TurnoverLimit'().
1111
-type invoice() :: dmsl_domain_thrift:'Invoice'().
1212
-type payment() :: dmsl_domain_thrift:'InvoicePayment'().
13+
-type session() :: hg_session:t().
1314
-type route() :: hg_route:payment_route().
1415
-type refund() :: hg_invoice_payment:domain_refund().
1516
-type cash() :: dmsl_domain_thrift:'Cash'().
@@ -21,18 +22,18 @@
2122
-export_type([turnover_limit_value/0]).
2223

2324
-export([get_turnover_limits/2]).
24-
-export([check_limits/5]).
25+
-export([check_limits/6]).
2526
-export([check_shop_limits/5]).
26-
-export([hold_payment_limits/5]).
27+
-export([hold_payment_limits/6]).
2728
-export([hold_shop_limits/5]).
2829
-export([hold_refund_limits/5]).
29-
-export([commit_payment_limits/6]).
30+
-export([commit_payment_limits/7]).
3031
-export([commit_shop_limits/5]).
3132
-export([commit_refund_limits/5]).
32-
-export([rollback_payment_limits/6]).
33+
-export([rollback_payment_limits/7]).
3334
-export([rollback_shop_limits/6]).
3435
-export([rollback_refund_limits/5]).
35-
-export([get_limit_values/5]).
36+
-export([get_limit_values/6]).
3637

3738
-define(route(ProviderRef, TerminalRef), #domain_PaymentRoute{
3839
provider = ProviderRef,
@@ -77,9 +78,10 @@ filter_existing_turnover_limits(Limits, Mode) ->
7778
Limits
7879
).
7980

80-
-spec get_limit_values([turnover_limit()], invoice(), payment(), route(), pos_integer()) -> [turnover_limit_value()].
81-
get_limit_values(TurnoverLimits, Invoice, Payment, Route, Iter) ->
82-
Context = gen_limit_context(Invoice, Payment, Route),
81+
-spec get_limit_values([turnover_limit()], invoice(), payment(), session() | undefined, route(), pos_integer()) ->
82+
[turnover_limit_value()].
83+
get_limit_values(TurnoverLimits, Invoice, Payment, Session, Route, Iter) ->
84+
Context = gen_limit_context(Invoice, Payment, Session, Route),
8385
get_limit_values(Context, TurnoverLimits, make_route_operation_segments(Invoice, Payment, Route, Iter)).
8486

8587
make_route_operation_segments(Invoice, Payment, ?route(ProviderRef, TerminalRef), Iter) ->
@@ -105,11 +107,11 @@ get_batch_limit_values(Context, TurnoverLimits, OperationIdSegments) ->
105107
hg_limiter_client:get_batch(LimitRequest, Context)
106108
).
107109

108-
-spec check_limits([turnover_limit()], invoice(), payment(), route(), pos_integer()) ->
110+
-spec check_limits([turnover_limit()], invoice(), payment(), session() | undefined, route(), pos_integer()) ->
109111
{ok, [turnover_limit_value()]}
110112
| {error, {limit_overflow, [binary()], [turnover_limit_value()]}}.
111-
check_limits(TurnoverLimits, Invoice, Payment, Route, Iter) ->
112-
Context = gen_limit_context(Invoice, Payment, Route),
113+
check_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter) ->
114+
Context = gen_limit_context(Invoice, Payment, Session, Route),
113115
Limits = get_limit_values(Context, TurnoverLimits, make_route_operation_segments(Invoice, Payment, Route, Iter)),
114116
try
115117
ok = check_limits_(Limits, Context),
@@ -166,9 +168,10 @@ check_limits_([TurnoverLimitValue | TLVs], Context) ->
166168
throw(limit_overflow)
167169
end.
168170

169-
-spec hold_payment_limits([turnover_limit()], invoice(), payment(), route(), pos_integer()) -> ok.
170-
hold_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter) ->
171-
Context = gen_limit_context(Invoice, Payment, Route),
171+
-spec hold_payment_limits([turnover_limit()], invoice(), payment(), session() | undefined, route(), pos_integer()) ->
172+
ok.
173+
hold_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter) ->
174+
Context = gen_limit_context(Invoice, Payment, Session, Route),
172175
ok = batch_hold_limits(Context, TurnoverLimits, make_route_operation_segments(Invoice, Payment, Route, Iter)).
173176

174177
batch_hold_limits(_Context, [], _OperationIdSegments) ->
@@ -197,9 +200,17 @@ make_refund_operation_segments(Invoice, Payment, Refund) ->
197200
{refund_session, get_refund_id(Refund)}
198201
].
199202

200-
-spec commit_payment_limits([turnover_limit()], invoice(), payment(), route(), pos_integer(), cash() | undefined) -> ok.
201-
commit_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, CapturedCash) ->
202-
Context = gen_limit_context(Invoice, Payment, Route, CapturedCash),
203+
-spec commit_payment_limits(
204+
[turnover_limit()],
205+
invoice(),
206+
payment(),
207+
session() | undefined,
208+
route(),
209+
pos_integer(),
210+
cash() | undefined
211+
) -> ok.
212+
commit_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, CapturedCash) ->
213+
Context = gen_limit_context(Invoice, Payment, Session, Route, CapturedCash),
203214
OperationIdSegments = make_route_operation_segments(Invoice, Payment, Route, Iter),
204215
ok = batch_commit_limits(Context, TurnoverLimits, OperationIdSegments).
205216

@@ -243,10 +254,18 @@ batch_commit_limits(Context, TurnoverLimits, OperationIdSegments) ->
243254
%%
244255
%% - `ignore_not_found` -- does not raise error if limiter won't be able to
245256
%% find according posting plan in accountant service
246-
-spec rollback_payment_limits([turnover_limit()], invoice(), payment(), route(), pos_integer(), [handling_flag()]) ->
257+
-spec rollback_payment_limits(
258+
[turnover_limit()],
259+
invoice(),
260+
payment(),
261+
session() | undefined,
262+
route(),
263+
pos_integer(),
264+
[handling_flag()]
265+
) ->
247266
ok.
248-
rollback_payment_limits(TurnoverLimits, Invoice, Payment, Route, Iter, Flags) ->
249-
Context = gen_limit_context(Invoice, Payment, Route),
267+
rollback_payment_limits(TurnoverLimits, Invoice, Payment, Session, Route, Iter, Flags) ->
268+
Context = gen_limit_context(Invoice, Payment, Session, Route),
250269
OperationIdSegments = make_route_operation_segments(Invoice, Payment, Route, Iter),
251270
ok = batch_rollback_limits(Context, TurnoverLimits, OperationIdSegments, Flags).
252271

@@ -281,10 +300,10 @@ rollback_refund_limits(TurnoverLimits, Invoice, Payment, Refund, Route) ->
281300
OperationIdSegments = make_refund_operation_segments(Invoice, Payment, Refund),
282301
ok = batch_rollback_limits(Context, TurnoverLimits, OperationIdSegments, []).
283302

284-
gen_limit_context(Invoice, Payment, Route) ->
285-
gen_limit_context(Invoice, Payment, Route, undefined).
303+
gen_limit_context(Invoice, Payment, Session, Route) ->
304+
gen_limit_context(Invoice, Payment, Session, Route, undefined).
286305

287-
gen_limit_context(Invoice, Payment, Route, CapturedCash) ->
306+
gen_limit_context(Invoice, Payment, Session, Route, CapturedCash) ->
288307
PaymentCtx = #context_payproc_InvoicePayment{
289308
payment = Payment#domain_InvoicePayment{
290309
status = {captured, #domain_InvoicePaymentCaptured{cost = CapturedCash}}
@@ -296,11 +315,17 @@ gen_limit_context(Invoice, Payment, Route, CapturedCash) ->
296315
op = {invoice_payment, #context_payproc_OperationInvoicePayment{}},
297316
invoice = #context_payproc_Invoice{
298317
invoice = Invoice,
299-
payment = PaymentCtx
318+
payment = PaymentCtx,
319+
session = gen_limit_session_context(Session, Route)
300320
}
301321
}
302322
}.
303323

324+
gen_limit_session_context(#{status := finished, route := Route}, Route) ->
325+
#context_payproc_InvoicePaymentSession{};
326+
gen_limit_session_context(_, _) ->
327+
undefined.
328+
304329
gen_limit_shop_context(Invoice, Payment) ->
305330
#limiter_LimitContext{
306331
payment_processing = #context_payproc_Context{

0 commit comments

Comments
 (0)