Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
519fb52
add bender client
aenglisc Sep 28, 2020
6719f45
update to shumaich proto
aenglisc Sep 28, 2020
72d899f
add bender, shumaich to app srcs
aenglisc Sep 28, 2020
e2cbb84
update pm_accounting
aenglisc Sep 28, 2020
92892a6
update hg_accounting
aenglisc Sep 28, 2020
d73a64d
update ct helper
aenglisc Sep 28, 2020
2b6d42b
add bender to mg config
aenglisc Sep 28, 2020
151d197
add bender to compose
aenglisc Sep 28, 2020
10faf83
add bender to sys config
aenglisc Sep 28, 2020
e11093d
add shumaich docker environment
aenglisc Oct 3, 2020
0ddfff2
use epic proto
aenglisc Oct 9, 2020
57f22c7
Merge branch 'master' into HG-544/ft/shumaich_proto
aenglisc Oct 9, 2020
b7fadae
update hg_proto
aenglisc Oct 9, 2020
229384b
update pm_proto
aenglisc Oct 9, 2020
7ecd02c
improved compose
aenglisc Oct 9, 2020
f6afc8f
update sys.config
aenglisc Oct 9, 2020
58264e7
update pm ct helper
aenglisc Oct 9, 2020
384a6be
update create_account in pm
aenglisc Oct 9, 2020
e78d963
add clock update event
aenglisc Oct 9, 2020
f462719
rework hg_accounting
aenglisc Oct 9, 2020
b66641f
update hg_ct_helper
aenglisc Oct 9, 2020
4e1e85b
add sequence generation utility
aenglisc Oct 9, 2020
39b9e2b
add clock update event to tests
aenglisc Oct 9, 2020
d0b3d82
payment flow updates
aenglisc Oct 9, 2020
3e6201c
fix config formatting
aenglisc Oct 9, 2020
f700d1b
use formatter
aenglisc Oct 9, 2020
8136a08
update damsel
aenglisc Oct 13, 2020
8ef7a32
rework clock update event
aenglisc Oct 13, 2020
b9cde04
Merge branch 'master' into HG-544/ft/shumaich_proto
aenglisc Oct 16, 2020
3e15ed7
update payment events
aenglisc Nov 3, 2020
19a4fe1
update compose
aenglisc Nov 3, 2020
8f889dd
update accounting
aenglisc Nov 3, 2020
4169681
add clock handling to payment events
aenglisc Nov 3, 2020
40e2d81
add clock handling to chargebacks
aenglisc Nov 3, 2020
e8e872e
update ct_helper
aenglisc Nov 3, 2020
f205816
Merge branch 'HG-544/ft/shumaich_proto' of github.com:rbkmoney/hellga…
aenglisc Nov 3, 2020
a34d01a
testing chargebacks
aenglisc Nov 16, 2020
f14836b
run fmt
aenglisc Nov 16, 2020
5c1303e
update .app.src
aenglisc Nov 16, 2020
04f16e3
some type updates
aenglisc Nov 25, 2020
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
16 changes: 16 additions & 0 deletions apps/hellgate/include/payment_events.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
{invoice_payment_cash_flow_changed, #payproc_InvoicePaymentCashFlowChanged{cash_flow = CashFlow}}
).

-define(payment_clock_update(Clock),
{invoice_payment_clock_update, #payproc_InvoicePaymentClockUpdate{clock = Clock}}
).

-define(payment_status_changed(Status),
{invoice_payment_status_changed, #payproc_InvoicePaymentStatusChanged{status = Status}}
).
Expand Down Expand Up @@ -336,6 +340,18 @@
}}
).

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

-define(refund_clock_update(Clock),
{invoice_payment_refund_clock_update, #payproc_InvoicePaymentClockUpdate{clock = Clock}}
).

-define(adjustment_clock_update(Clock),
{invoice_payment_adjustment_clock_update, #payproc_InvoicePaymentClockUpdate{clock = Clock}}
).

-define(refund_rollback_started(Failure),
{invoice_payment_refund_rollback_started, #payproc_InvoicePaymentRefundRollbackStarted{reason = Failure}}
).
Expand Down
1 change: 1 addition & 0 deletions apps/hellgate/src/hellgate.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
gproc,
dmt_client,
party_client,
bender_client,
woody_user_identity,
payproc_errors,
erl_health,
Expand Down
179 changes: 117 additions & 62 deletions apps/hellgate/src/hg_accounting.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,34 @@
-module(hg_accounting).

-export([get_account/1]).
-export([get_account/2]).

-export([get_balance/1]).
-export([get_balance/2]).

-export([create_account/1]).
-export([create_account/2]).

-export([collect_account_map/6]).
-export([collect_merchant_account_map/2]).
-export([collect_provider_account_map/3]).
-export([collect_system_account_map/5]).
-export([collect_external_account_map/4]).

-export([hold/2]).
-export([plan/2]).
-export([commit/2]).
-export([rollback/2]).
-export([hold/3]).
-export([hold/4]).

-export([plan/3]).
-export([plan/4]).

-export([commit/3]).
-export([commit/4]).

-export([rollback/3]).
-export([rollback/4]).

-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
-include_lib("shumpune_proto/include/shumaich_shumaich_thrift.hrl").

-type amount() :: dmsl_domain_thrift:'Amount'().
-type currency_code() :: dmsl_domain_thrift:'CurrencySymbolicCode'().
Expand All @@ -34,7 +44,7 @@
-type batch_id() :: dmsl_accounter_thrift:'BatchID'().
-type final_cash_flow() :: dmsl_domain_thrift:'FinalCashFlow'().
-type batch() :: {batch_id(), final_cash_flow()}.
-type clock() :: shumpune_shumpune_thrift:'Clock'().
-type clock() :: domain_thrift:'AccounterClock'().

-type payment() :: dmsl_domain_thrift:'InvoicePayment'().
-type shop() :: dmsl_domain_thrift:'Shop'().
Expand All @@ -54,44 +64,48 @@
account_id => account_id(),
own_amount => amount(),
min_available_amount => amount(),
max_available_amount => amount()
max_available_amount => amount(),
clock => clock()
}.

-spec get_account(account_id()) -> account().
get_account(AccountID) ->
case call_accounter('GetAccountByID', {AccountID}) of
get_account(AccountID, undefined).

-spec get_account(account_id(), clock()) -> account().
get_account(AccountID, Clock) ->
case call_accounter('GetAccountByID', {AccountID, to_accounter_clock(Clock)}) of
{ok, Result} ->
construct_account(AccountID, Result);
{exception, #shumpune_AccountNotFound{}} ->
hg_woody_wrapper:raise(#payproc_AccountNotFound{})
{exception, #shumaich_AccountNotFound{}} ->
hg_woody_wrapper:raise(#payproc_AccountNotFound{});
% FIXME: this should probably work differently, hg_retry?
{exception, #shumaich_NotReady{}} ->
get_account(AccountID, Clock)
end.

-spec get_balance(account_id()) -> balance().
get_balance(AccountID) ->
get_balance(AccountID, {latest, #shumpune_LatestClock{}}).
get_balance(AccountID, undefined).

-spec get_balance(account_id(), clock()) -> balance().
get_balance(AccountID, Clock) ->
case call_accounter('GetBalanceByID', {AccountID, Clock}) of
case call_accounter('GetBalanceByID', {AccountID, to_accounter_clock(Clock)}) of
{ok, Result} ->
construct_balance(AccountID, Result);
{exception, #shumpune_AccountNotFound{}} ->
hg_woody_wrapper:raise(#payproc_AccountNotFound{})
{exception, #shumaich_AccountNotFound{}} ->
hg_woody_wrapper:raise(#payproc_AccountNotFound{});
% FIXME: this should probably work differently, hg_retry?
{exception, #shumaich_NotReady{}} ->
get_balance(AccountID, Clock)
end.

-spec create_account(currency_code()) -> account_id().
create_account(CurrencyCode) ->
create_account(CurrencyCode, undefined).

-spec create_account(currency_code(), binary() | undefined) -> account_id().
create_account(CurrencyCode, Description) ->
case call_accounter('CreateAccount', {construct_prototype(CurrencyCode, Description)}) of
{ok, Result} ->
Result;
{exception, Exception} ->
% FIXME
error({accounting, Exception})
end.
create_account(_CurrencyCode) ->
WoodyCtx = hg_context:get_woody_context(hg_context:load()),
% FIXME: placeholder, the sequence id should probably be passed externally
% not sure about the minimum too
hg_utils:gen_sequence(<<"create_shumaich_account">>, WoodyCtx, #{minimum => 10000}).

-spec collect_account_map(payment(), shop(), payment_institution(), provider(), varset(), revision()) -> map().
collect_account_map(Payment, Shop, PaymentInstitution, Provider, VS, Revision) ->
Expand Down Expand Up @@ -137,60 +151,91 @@ collect_external_account_map(Payment, VS, Revision, Acc) ->
Acc
end.

construct_prototype(CurrencyCode, Description) ->
#shumpune_AccountPrototype{
currency_sym_code = CurrencyCode,
description = Description
}.

%%
-spec plan(plan_id(), [batch()]) -> clock().
plan(_PlanID, []) ->
-spec plan(plan_id(), [batch()], hg_datetime:timestamp()) -> clock().
plan(_PlanID, [], _Timestamp) ->
error(badarg);
plan(_PlanID, Batches, _Timestamp) when not is_list(Batches) ->
error(badarg);
plan(PlanID, Batches, Timestamp) ->
lists:foldl(
fun(Batch, _) -> hold(PlanID, Batch, Timestamp) end,
undefined,
Batches
).

-spec plan(plan_id(), [batch()], hg_datetime:timestamp(), clock()) -> clock().
plan(_PlanID, [], _Timestamp, _Clock) ->
error(badarg);
plan(_PlanID, Batches) when not is_list(Batches) ->
plan(_PlanID, Batches, _Timestamp, _Clock) when not is_list(Batches) ->
error(badarg);
plan(PlanID, Batches) ->
plan(PlanID, Batches, Timestamp, Clock) ->
lists:foldl(
fun(Batch, _) -> hold(PlanID, Batch) end,
fun(Batch, _) -> hold(PlanID, Batch, Timestamp, Clock) end,
undefined,
Batches
).

-spec hold(plan_id(), batch()) -> clock().
hold(PlanID, Batch) ->
do('Hold', construct_plan_change(PlanID, Batch)).
-spec hold(plan_id(), batch(), hg_datetime:timestamp()) -> clock().
hold(PlanID, Batch, Timestamp) ->
do('Hold', construct_plan_change(PlanID, Batch, Timestamp)).

-spec hold(plan_id(), batch(), hg_datetime:timestamp(), clock()) -> clock().
hold(PlanID, Batches, Timestamp, Clock) ->
AccounterClock = to_accounter_clock(Clock),
do('Hold', construct_plan_change(PlanID, Batches, Timestamp), AccounterClock).

-spec commit(plan_id(), [batch()], hg_datetime:timestamp()) -> clock().
commit(PlanID, Batches, Timestamp) ->
do('CommitPlan', construct_plan(PlanID, Batches, Timestamp)).

-spec commit(plan_id(), [batch()], hg_datetime:timestamp(), clock()) -> clock().
commit(PlanID, Batches, Timestamp, Clock) ->
AccounterClock = to_accounter_clock(Clock),
do('CommitPlan', construct_plan(PlanID, Batches, Timestamp), AccounterClock).

-spec commit(plan_id(), [batch()]) -> clock().
commit(PlanID, Batches) ->
do('CommitPlan', construct_plan(PlanID, Batches)).
-spec rollback(plan_id(), [batch()], hg_datetime:timestamp()) -> clock().
rollback(PlanID, Batches, Timestamp) ->
do('RollbackPlan', construct_plan(PlanID, Batches, Timestamp)).

-spec rollback(plan_id(), [batch()]) -> clock().
rollback(PlanID, Batches) ->
do('RollbackPlan', construct_plan(PlanID, Batches)).
-spec rollback(plan_id(), [batch()], hg_datetime:timestamp(), clock()) -> clock().
rollback(PlanID, Batches, Timestamp, Clock) ->
AccounterClock = to_accounter_clock(Clock),
do('RollbackPlan', construct_plan(PlanID, Batches, Timestamp), AccounterClock).

do(Op, Plan) ->
case call_accounter(Op, {Plan}) of
do(Op, Plan, {latest, #shumaich_LatestClock{}}).

do(Op, Plan, PreviousClock) ->
case call_accounter(Op, {Plan, PreviousClock}) of
{ok, Clock} ->
Clock;
to_domain_clock(Clock);
{exception, #shumaich_NotReady{}} ->
erlang:display({'NOT READY', Op, Plan#shumaich_PostingPlan.id}),
% FIXME: maybe some other way?
ok = timer:sleep(200),
do(Op, Plan, PreviousClock);
{exception, Exception} ->
% FIXME
error({accounting, Exception})
end.

construct_plan_change(PlanID, {BatchID, Cashflow}) ->
#shumpune_PostingPlanChange{
construct_plan_change(PlanID, {BatchID, Cashflow}, Timestamp) ->
#shumaich_PostingPlanChange{
id = PlanID,
batch = #shumpune_PostingBatch{
creation_time = Timestamp,
batch = #shumaich_PostingBatch{
id = BatchID,
postings = collect_postings(Cashflow)
}
}.

construct_plan(PlanID, Batches) ->
#shumpune_PostingPlan{
construct_plan(PlanID, Batches, Timestamp) ->
#shumaich_PostingPlan{
id = PlanID,
creation_time = Timestamp,
batch_list = [
#shumpune_PostingBatch{
#shumaich_PostingBatch{
id = BatchID,
postings = collect_postings(Cashflow)
}
Expand All @@ -200,11 +245,11 @@ construct_plan(PlanID, Batches) ->

collect_postings(Cashflow) ->
[
#shumpune_Posting{
from_id = Source,
to_id = Destination,
#shumaich_Posting{
from_account = #shumaich_Account{id = Source, currency_symbolic_code = CurrencyCode},
to_account = #shumaich_Account{id = Destination, currency_symbolic_code = CurrencyCode},
amount = Amount,
currency_sym_code = CurrencyCode,
currency_symbolic_code = CurrencyCode,
description = construct_posting_description(Details)
}
|| #domain_FinalCashFlowPosting{
Expand All @@ -227,8 +272,8 @@ construct_posting_description(undefined) ->

construct_account(
AccountID,
#shumpune_Account{
currency_sym_code = CurrencyCode
#shumaich_Account{
currency_symbolic_code = CurrencyCode
}
) ->
#{
Expand All @@ -238,17 +283,19 @@ construct_account(

construct_balance(
AccountID,
#shumpune_Balance{
#shumaich_Balance{
own_amount = OwnAmount,
min_available_amount = MinAvailableAmount,
max_available_amount = MaxAvailableAmount
% clock = Clock
}
) ->
#{
account_id => AccountID,
own_amount => OwnAmount,
min_available_amount => MinAvailableAmount,
max_available_amount => MaxAvailableAmount
% clock => to_domain_clock(Clock)
}.

%%
Expand All @@ -261,3 +308,11 @@ get_payment_cost(#domain_InvoicePayment{cost = Cost}) ->

get_currency(#domain_Cash{currency = Currency}) ->
Currency.

to_domain_clock({vector, #shumaich_VectorClock{state = State}}) ->
{vector, #domain_VectorClock{state = State}}.

to_accounter_clock(undefined) ->
{latest, #shumaich_LatestClock{}};
to_accounter_clock({vector, #domain_VectorClock{state = State}}) ->
{vector, #shumaich_VectorClock{state = State}}.
Loading