Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
9ae8b9d
add chargeback clock event
aenglisc Dec 3, 2020
6435b7e
add clock event handling to chargeback
aenglisc Dec 3, 2020
6c950db
update some tests
aenglisc Dec 4, 2020
f01c609
update chargeback handling
aenglisc Dec 4, 2020
f9f27ee
cleanup chargebacks
aenglisc Dec 4, 2020
6c30541
more cleaning up
aenglisc Dec 4, 2020
b8fc370
run format
aenglisc Dec 4, 2020
5a4e8b5
Merge branch 'HG-544/ft/shumaich_payments' into HG-544/ft/shumaich_ch…
kehitt Jul 8, 2021
5db1283
fix dialyzer
kehitt Jul 9, 2021
0807343
Merge branch 'HG-544/ft/shumaich_payments' into HG-544/ft/shumaich_ch…
kehitt Jul 12, 2021
6638fef
uncomment test
kehitt Jul 12, 2021
d081737
Merge branch 'HG-544/ft/shumaich_payments' into HG-544/ft/shumaich_ch…
kehitt Jul 12, 2021
2e12caf
update tests with new get_balance
kehitt Jul 12, 2021
6da85b1
typo fix
kehitt Jul 12, 2021
59e5cfe
Revert "typo fix"
kehitt Jul 13, 2021
be2fe42
Revert "update tests with new get_balance"
kehitt Jul 13, 2021
caee121
Merge branch 'HG-544/ft/shumaich_payments' into HG-544/ft/shumaich_ch…
kehitt Jul 13, 2021
8ccaf63
attmept to fix the tests
kehitt Jul 13, 2021
fd1ec4e
drop specific clock
kehitt Jul 13, 2021
239fa28
Merge branch 'HG-544/ft/shumaich_payments' into HG-544/ft/shumaich_ch…
kehitt Jul 14, 2021
a45348e
some, but still not all, fixes for tests
kehitt Jul 14, 2021
a717600
fix balance min_value
kehitt Jul 14, 2021
6a975bc
pass clock to get_balance for chargeback
kehitt Jul 14, 2021
9f38487
fix match
kehitt Jul 14, 2021
8a710aa
fix balance checks
kehitt Jul 14, 2021
953bc87
Merge branch 'HG-544/ft/shumaich_payments' into HG-544/ft/shumaich_ch…
kehitt Jul 14, 2021
43aa3ac
Merge branch 'HG-544/ft/shumaich_payments' into HG-544/ft/shumaich_ch…
kehitt Jul 15, 2021
cf718d5
boost timeout values
kehitt Jul 15, 2021
a391675
fix lint
kehitt Jul 15, 2021
8c5a95f
fix hold_lifetime
kehitt Jul 15, 2021
d309afd
???
kehitt Jul 15, 2021
0c04b7a
tst
kehitt Jul 15, 2021
a681572
revert lifetime changes
kehitt Jul 16, 2021
2701323
get clock from payment, update payment clock when done
kehitt Jul 22, 2021
35a6957
remove excessive type definition
kehitt Jul 23, 2021
6889d5d
merge clocks
kehitt Aug 5, 2021
8658d5f
formatting, argument order
kehitt Aug 6, 2021
b48aca4
small review fixes
kehitt Aug 16, 2021
e7f6dde
use existing test methods where convinient
kehitt Aug 17, 2021
fb00cdf
Merge remote-tracking branch 'origin/HG-544/ft/shumaich_payments' int…
kehitt Sep 21, 2021
4a4f066
update chargebacks for new accounter api
kehitt Sep 21, 2021
7dbcc1c
Merge remote-tracking branch 'origin/HG-544/ft/shumaich_payments' int…
kehitt Sep 22, 2021
9510a6d
raise resource unavailable when accounter is not ready
kehitt Sep 22, 2021
a2e7af3
Merge remote-tracking branch 'origin/HG-544/ft/shumaich_payments' int…
kehitt Sep 22, 2021
45937c0
Merge remote-tracking branch 'origin/HG-544/ft/shumaich_payments' int…
kehitt Sep 23, 2021
bcd4877
Merge remote-tracking branch 'origin/HG-544/ft/shumaich_payments' int…
kehitt Sep 23, 2021
484569f
avoide resource_unavailable when possible
kehitt Sep 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/hellgate/include/payment_events.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@
}}
).

-define(chargeback_clock_update(Clock),
{invoice_payment_chargeback_clock_update, #payproc_InvoicePaymentClockUpdate{clock = Clock}}
).

-define(chargeback_stage_chargeback(),
{chargeback, #domain_InvoicePaymentChargebackStageChargeback{}}
).
Expand Down
71 changes: 61 additions & 10 deletions apps/hellgate/src/hg_invoice_payment.erl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
-export([get_adjustments/1]).
-export([get_adjustment/2]).
-export([get_trx/1]).
-export([get_clock/1]).

-export([get_final_cashflow/1]).
-export([get_sessions/1]).
Expand Down Expand Up @@ -961,8 +962,7 @@ collect_cash_flow_context(
get_available_amount(AccountID, Clock) ->
#{
min_available_amount := AvailableAmount
} =
hg_accounting:get_balance(AccountID, Clock),
} = hg_accounting:get_balance(AccountID, Clock),
AvailableAmount.

construct_payment_plan_id(St) ->
Expand Down Expand Up @@ -1906,13 +1906,31 @@ process_chargeback(Type = finalising_accounter, ID, Action0, St) ->
ChargebackBody = hg_invoice_payment_chargeback:get_body(ChargebackState),
ChargebackTarget = hg_invoice_payment_chargeback:get_target_status(ChargebackState),
MaybeChargedback = maybe_set_charged_back_status(ChargebackTarget, ChargebackBody, St),
{Changes, Action1} = hg_invoice_payment_chargeback:process_timeout(Type, ChargebackState, Action0, ChargebackOpts),
{done, {[?chargeback_ev(ID, C) || C <- Changes] ++ MaybeChargedback, Action1}};
case
hg_invoice_payment_chargeback:process_timeout(
Type,
ChargebackState,
St,
Action0,
ChargebackOpts
)
of
{done, {Changes, Action1}} ->
{done, {[?chargeback_ev(ID, C) || C <- Changes] ++ MaybeChargedback, Action1}};
{next, {[], _Action}} = Result ->
Result
end;
process_chargeback(Type, ID, Action0, St) ->
ChargebackState = get_chargeback_state(ID, St),
ChargebackOpts = get_chargeback_opts(St),
{Changes, Action1} = hg_invoice_payment_chargeback:process_timeout(Type, ChargebackState, Action0, ChargebackOpts),
{done, {[?chargeback_ev(ID, C) || C <- Changes], Action1}}.
{Result, {Changes, Action1}} = hg_invoice_payment_chargeback:process_timeout(
Type,
ChargebackState,
St,
Action0,
ChargebackOpts
),
{Result, {[?chargeback_ev(ID, C) || C <- Changes], Action1}}.

maybe_set_charged_back_status(?chargeback_status_accepted(), ChargebackBody, St) ->
InterimPaymentAmount = get_remaining_payment_balance(St),
Expand Down Expand Up @@ -3024,13 +3042,37 @@ merge_change(Change = ?chargeback_ev(ID, Event), St, Opts) ->
_ = validate_transition([idle, {chargeback, ID, updating_chargeback}], Change, St, Opts),
St#st{activity = {chargeback, ID, updating_chargeback}};
?chargeback_cash_flow_changed(_) ->
Valid = [{chargeback, ID, Activity} || Activity <- [preparing_initial_cash_flow, updating_cash_flow]],
Valid = [
{chargeback, ID, Activity}
|| Activity <- [
preparing_initial_cash_flow,
updating_cash_flow
]
],
_ = validate_transition(Valid, Change, St, Opts),
case St of
#st{activity = {chargeback, ID, preparing_initial_cash_flow}} ->
St#st{activity = idle};
St#st{activity = {chargeback, ID, holding_initial_cash_flow}};
#st{activity = {chargeback, ID, updating_cash_flow}} ->
St#st{activity = {chargeback, ID, finalising_accounter}}
St#st{activity = {chargeback, ID, holding_updated_cash_flow}}
end;
?chargeback_clock_update(_) ->
Valid = [
{chargeback, ID, Activity}
|| Activity <- [
finalising_accounter,
holding_initial_cash_flow,
holding_updated_cash_flow
]
],
_ = validate_transition(Valid, Change, St, Opts),
case St of
#st{activity = {chargeback, ID, holding_initial_cash_flow}} ->
St#st{activity = idle};
#st{activity = {chargeback, ID, holding_updated_cash_flow}} ->
St#st{activity = {chargeback, ID, finalising_accounter}};
#st{activity = {chargeback, ID, finalising_accounter}} ->
St
end;
?chargeback_target_status_changed(?chargeback_status_accepted()) ->
_ = validate_transition([idle, {chargeback, ID, updating_chargeback}], Change, St, Opts),
Expand All @@ -3048,7 +3090,7 @@ merge_change(Change = ?chargeback_ev(ID, Event), St, Opts) ->
St#st{activity = idle}
end,
ChargebackSt = merge_chargeback_change(Event, try_get_chargeback_state(ID, St1)),
set_chargeback_state(ID, ChargebackSt, St1);
set_chargeback_clock(Event, set_chargeback_state(ID, ChargebackSt, St1));
merge_change(Change = ?refund_ev(ID, Event), St, Opts) ->
St1 =
case Event of
Expand Down Expand Up @@ -3175,6 +3217,11 @@ save_retry_attempt(Target, #st{retry_attempts = Attempts} = St) ->
merge_chargeback_change(Change, ChargebackState) ->
hg_invoice_payment_chargeback:merge_change(Change, ChargebackState).

set_chargeback_clock(?chargeback_clock_update(Clock), St = #st{}) ->
St#st{clock = Clock};
set_chargeback_clock(_, St = #st{}) ->
St.

merge_refund_change(?refund_created(Refund, Cashflow, TransactionInfo), undefined) ->
#refund_st{refund = Refund, cash_flow = Cashflow, transaction_info = TransactionInfo};
merge_refund_change(?refund_status_changed(Status), RefundSt) ->
Expand Down Expand Up @@ -3270,6 +3317,10 @@ get_trx(#st{trx = Trx}) ->
set_trx(Trx, St = #st{}) ->
St#st{trx = Trx}.

-spec get_clock(st()) -> hg_accounting_new:clock().
get_clock(#st{clock = Clock}) ->
Clock.

try_get_refund_state(ID, #st{refunds = Rs}) ->
case Rs of
#{ID := RefundSt} ->
Expand Down
85 changes: 60 additions & 25 deletions apps/hellgate/src/hg_invoice_payment_chargeback.erl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
-export(
[
merge_change/2,
process_timeout/4
process_timeout/5
]
).

Expand Down Expand Up @@ -75,12 +75,16 @@
-type opts() :: #{
payment_state := payment_state(),
party := party(),
invoice := invoice()
invoice := invoice(),
timestamp := hg_datetime:timestamp()
}.

-type payment_state() ::
hg_invoice_payment:st().

-type clock() ::
hg_accounting_new:clock().

-type party() ::
dmsl_domain_thrift:'Party'().

Expand Down Expand Up @@ -112,7 +116,7 @@
dmsl_domain_thrift:'FinalCashFlow'().

-type batch() ::
hg_accounting:batch().
hg_accounting_new:batch().

-type create_params() ::
dmsl_payment_processing_thrift:'InvoicePaymentChargebackParams'().
Expand All @@ -132,6 +136,9 @@
-type result() ::
{[change()], action()}.

-type machine_result() ::
{next | done, result()}.

-type change() ::
dmsl_payment_processing_thrift:'InvoicePaymentChargebackChangePayload'().

Expand All @@ -140,8 +147,10 @@

-type activity() ::
preparing_initial_cash_flow
| holding_initial_cash_flow
| updating_chargeback
| updating_cash_flow
| holding_updated_cash_flow
| finalising_accounter.

-spec get(state()) -> chargeback().
Expand Down Expand Up @@ -263,16 +272,22 @@ merge_change(?chargeback_target_status_changed(Status), State) ->
set_target_status(Status, State);
merge_change(?chargeback_status_changed(Status), State) ->
set_target_status(undefined, set_status(Status, State));
merge_change(?chargeback_clock_update(_), State) ->
State;
merge_change(?chargeback_cash_flow_changed(CashFlow), State) ->
set_cash_flow(CashFlow, State).

-spec process_timeout(activity(), state(), action(), opts()) -> result().
process_timeout(preparing_initial_cash_flow, State, _Action, Opts) ->
update_cash_flow(State, hg_machine_action:new(), Opts);
process_timeout(updating_cash_flow, State, _Action, Opts) ->
-spec process_timeout(activity(), state(), payment_state(), action(), opts()) -> machine_result().
process_timeout(preparing_initial_cash_flow, State, _PaymentSt, _Action, Opts) ->
update_cash_flow(State, hg_machine_action:instant(), Opts);
process_timeout(holding_initial_cash_flow, State, PaymentSt, _Action, Opts) ->
hold_cash_flow(State, PaymentSt, hg_machine_action:new(), Opts);
process_timeout(updating_cash_flow, State, _PaymentSt, _Action, Opts) ->
update_cash_flow(State, hg_machine_action:instant(), Opts);
process_timeout(finalising_accounter, State, Action, Opts) ->
finalise(State, Action, Opts).
process_timeout(holding_updated_cash_flow, State, PaymentSt, _Action, Opts) ->
hold_cash_flow(State, PaymentSt, hg_machine_action:instant(), Opts);
process_timeout(finalising_accounter, State, PaymentSt, Action, Opts) ->
finalise(State, PaymentSt, Action, Opts).

%% Private

Expand Down Expand Up @@ -337,23 +352,37 @@ do_reopen(State, PaymentState, ReopenParams = ?reopen_params(Levy, Body)) ->

%%

-spec update_cash_flow(state(), action(), opts()) -> result() | no_return().
-spec update_cash_flow(state(), action(), opts()) -> machine_result() | no_return().
update_cash_flow(State, Action, Opts) ->
FinalCashFlow = build_chargeback_cash_flow(State, Opts),
UpdatedPlan = build_updated_plan(FinalCashFlow, State),
_ = prepare_cash_flow(State, UpdatedPlan, Opts),
{[?chargeback_cash_flow_changed(FinalCashFlow)], Action}.

-spec finalise(state(), action(), opts()) -> result() | no_return().
finalise(#chargeback_st{target_status = Status = ?chargeback_status_pending()}, Action, _Opts) ->
{[?chargeback_status_changed(Status)], Action};
finalise(State = #chargeback_st{target_status = Status}, Action, Opts) when
{done, {[?chargeback_cash_flow_changed(FinalCashFlow)], Action}}.

-spec hold_cash_flow(state(), payment_state(), action(), opts()) -> machine_result() | no_return().
hold_cash_flow(State, PaymentSt, Action, Opts) ->
CashFlowPlan = get_current_plan(State),
case prepare_cash_flow(get_clock(PaymentSt), State, CashFlowPlan, Opts) of
{ok, Clock} ->
{done, {[?chargeback_clock_update(Clock)], Action}};
{error, not_ready} ->
_ = logger:warning("Accounter was not ready, retrying"),
{next, {[], hg_machine_action:set_timeout(0, Action)}}
end.

-spec finalise(state(), payment_state(), action(), opts()) -> machine_result() | no_return().
finalise(#chargeback_st{target_status = Status = ?chargeback_status_pending()}, _PaymentSt, Action, _Opts) ->
{done, {[?chargeback_status_changed(Status)], Action}};
finalise(State = #chargeback_st{target_status = Status}, PaymentSt, Action, Opts) when
Status =:= ?chargeback_status_rejected();
Status =:= ?chargeback_status_accepted();
Status =:= ?chargeback_status_cancelled()
->
_ = commit_cash_flow(State, Opts),
{[?chargeback_status_changed(Status)], Action}.
case commit_cash_flow(get_clock(PaymentSt), State, Opts) of
{ok, Clock} ->
{done, {[?chargeback_clock_update(Clock), ?chargeback_status_changed(Status)], Action}};
{error, not_ready} ->
_ = logger:warning("Accounter was not ready, retrying"),
{next, {[], hg_machine_action:set_timeout(0, Action)}}
end.

-spec build_chargeback(opts(), create_params(), revision(), timestamp()) -> chargeback() | no_return().
build_chargeback(Opts, Params = ?chargeback_params(Levy, Body, Reason), Revision, CreatedAt) ->
Expand Down Expand Up @@ -430,7 +459,7 @@ build_chargeback_cash_flow(State, Opts) ->
PaymentInstitutionRef = get_payment_institution_ref(get_contract(Party, Shop)),
PaymentInst = hg_payment_institution:compute_payment_institution(PaymentInstitutionRef, VS, Revision),
Provider = get_route_provider(Route, Revision),
AccountMap = hg_accounting:collect_account_map(Payment, Shop, PaymentInst, Provider, VS, Revision),
AccountMap = hg_accounting_new:collect_account_map(Payment, Shop, PaymentInst, Provider, VS, Revision),
ServiceContext = build_service_cash_flow_context(State),
ProviderContext = build_provider_cash_flow_context(State, ProviderFees),
ServiceFinalCF = hg_cashflow:finalize(ServiceCashFlow, ServiceContext, AccountMap),
Expand Down Expand Up @@ -495,14 +524,16 @@ define_body(undefined, PaymentState) ->
define_body(Cash, _PaymentState) ->
Cash.

prepare_cash_flow(State, CashFlowPlan, Opts) ->
prepare_cash_flow(Clock, State, CashFlowPlan, Opts) ->
#{timestamp := Timestamp} = Opts,
PlanID = construct_chargeback_plan_id(State, Opts),
hg_accounting:plan(PlanID, CashFlowPlan).
hg_accounting_new:plan(PlanID, CashFlowPlan, Timestamp, Clock).

commit_cash_flow(State, Opts) ->
commit_cash_flow(Clock, State, Opts) ->
#{timestamp := Timestamp} = Opts,
CashFlowPlan = get_current_plan(State),
PlanID = construct_chargeback_plan_id(State, Opts),
hg_accounting:commit(PlanID, CashFlowPlan).
hg_accounting_new:commit(PlanID, CashFlowPlan, Timestamp, Clock).

construct_chargeback_plan_id(State, Opts) ->
{Stage, _} = get_stage(State),
Expand Down Expand Up @@ -605,6 +636,10 @@ get_current_plan(#chargeback_st{cash_flow_plans = Plans} = State) ->
#{Stage := Plan} = Plans,
Plan.

-spec get_clock(payment_state()) -> clock().
get_clock(PaymentSt) ->
hg_invoice_payment:get_clock(PaymentSt).

-spec get_reverted_previous_stage(state()) -> [batch()].
get_reverted_previous_stage(State) ->
case get_previous_stage(State) of
Expand Down
Loading