mirror of
https://github.com/valitydev/fistful-server.git
synced 2024-11-06 02:35:18 +00:00
TD-264: Move to accounter (#22)
* TD-264: Move to accounter * Hadofix * Hadofix 2 * Review fixes * Review fix
This commit is contained in:
parent
2586e6df84
commit
b2aec027fd
15
Dockerfile
15
Dockerfile
@ -2,6 +2,7 @@ ARG OTP_VERSION
|
||||
|
||||
# Build the release
|
||||
FROM docker.io/library/erlang:${OTP_VERSION} AS builder
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
# Install thrift compiler
|
||||
ARG THRIFT_VERSION
|
||||
@ -16,8 +17,8 @@ COPY . /build/
|
||||
|
||||
# Build the release
|
||||
WORKDIR /build
|
||||
RUN rebar3 compile
|
||||
RUN rebar3 as prod release
|
||||
RUN rebar3 compile && \
|
||||
rebar3 as prod release
|
||||
|
||||
# Make a runner image
|
||||
FROM docker.io/library/erlang:${OTP_VERSION}-slim
|
||||
@ -28,13 +29,15 @@ ARG SERVICE_NAME
|
||||
ENV CHARSET=UTF-8
|
||||
ENV LANG=C.UTF-8
|
||||
|
||||
# Expose SERVICE_NAME as env so CMD expands properly on start
|
||||
ENV SERVICE_NAME=${SERVICE_NAME}
|
||||
|
||||
# Set runtime
|
||||
WORKDIR /opt/${SERVICE_NAME}
|
||||
|
||||
COPY --from=builder /build/_build/prod/rel/${SERVICE_NAME} /opt/${SERVICE_NAME}
|
||||
|
||||
RUN echo "#!/bin/sh" >> /entrypoint.sh && \
|
||||
echo "exec /opt/${SERVICE_NAME}/bin/${SERVICE_NAME} foreground" >> /entrypoint.sh && \
|
||||
chmod +x /entrypoint.sh
|
||||
ENTRYPOINT []
|
||||
CMD /opt/${SERVICE_NAME}/bin/${SERVICE_NAME} foreground
|
||||
CMD ["/entrypoint.sh"]
|
||||
|
||||
EXPOSE 8022
|
||||
|
@ -1,6 +1,7 @@
|
||||
ARG OTP_VERSION
|
||||
|
||||
FROM docker.io/library/erlang:${OTP_VERSION}
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
ARG BUILDARCH
|
||||
|
||||
@ -15,4 +16,4 @@ ENV CHARSET=UTF-8
|
||||
ENV LANG=C.UTF-8
|
||||
|
||||
# Set runtime
|
||||
CMD /bin/bash
|
||||
CMD ["/bin/bash"]
|
||||
|
@ -16,29 +16,29 @@
|
||||
-export([proxy/2]).
|
||||
-export([proxy/3]).
|
||||
-export([proxy/4]).
|
||||
-export([system_account_set/4]).
|
||||
-export([external_account_set/4]).
|
||||
-export([system_account_set/3]).
|
||||
-export([external_account_set/3]).
|
||||
-export([term_set_hierarchy/1]).
|
||||
-export([term_set_hierarchy/2]).
|
||||
-export([term_set_hierarchy/3]).
|
||||
-export([timed_term_set/1]).
|
||||
-export([globals/2]).
|
||||
-export([withdrawal_provider/4]).
|
||||
-export([withdrawal_provider/3]).
|
||||
-export([withdrawal_terminal/1]).
|
||||
|
||||
%%
|
||||
|
||||
-include_lib("ff_cth/include/ct_domain.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
-include_lib("damsel/include/dmsl_accounter_thrift.hrl").
|
||||
|
||||
-define(DTP(Type), dmsl_domain_thrift:Type()).
|
||||
|
||||
-type object() ::
|
||||
dmsl_domain_thrift:'DomainObject'().
|
||||
|
||||
-spec withdrawal_provider(?DTP('ProviderRef'), ?DTP('ProxyRef'), binary(), ct_helper:config()) -> object().
|
||||
withdrawal_provider(?prv(16) = Ref, ProxyRef, IdentityID, C) ->
|
||||
AccountID = account(<<"RUB">>, C),
|
||||
-spec withdrawal_provider(?DTP('ProviderRef'), ?DTP('ProxyRef'), binary()) -> object().
|
||||
withdrawal_provider(?prv(16) = Ref, ProxyRef, IdentityID) ->
|
||||
{ok, AccountID} = ct_helper:create_account(<<"RUB">>),
|
||||
{provider, #domain_ProviderObject{
|
||||
ref = Ref,
|
||||
data = #domain_Provider{
|
||||
@ -59,8 +59,8 @@ withdrawal_provider(?prv(16) = Ref, ProxyRef, IdentityID, C) ->
|
||||
]}
|
||||
}
|
||||
}};
|
||||
withdrawal_provider(Ref, ProxyRef, IdentityID, C) ->
|
||||
AccountID = account(<<"RUB">>, C),
|
||||
withdrawal_provider(Ref, ProxyRef, IdentityID) ->
|
||||
{ok, AccountID} = ct_helper:create_account(<<"RUB">>),
|
||||
{provider, #domain_ProviderObject{
|
||||
ref = Ref,
|
||||
data = #domain_Provider{
|
||||
@ -400,10 +400,10 @@ proxy(Ref, Name, URL, Opts) ->
|
||||
}
|
||||
}}.
|
||||
|
||||
-spec system_account_set(?DTP('SystemAccountSetRef'), binary(), ?DTP('CurrencyRef'), ct_helper:config()) -> object().
|
||||
system_account_set(Ref, Name, ?cur(SymCode), C) ->
|
||||
AccountID1 = account(SymCode, C),
|
||||
AccountID2 = account(SymCode, C),
|
||||
-spec system_account_set(?DTP('SystemAccountSetRef'), binary(), ?DTP('CurrencyRef')) -> object().
|
||||
system_account_set(Ref, Name, ?cur(SymCode)) ->
|
||||
{ok, AccountID1} = ct_helper:create_account(SymCode),
|
||||
{ok, AccountID2} = ct_helper:create_account(SymCode),
|
||||
{system_account_set, #domain_SystemAccountSetObject{
|
||||
ref = Ref,
|
||||
data = #domain_SystemAccountSet{
|
||||
@ -418,11 +418,11 @@ system_account_set(Ref, Name, ?cur(SymCode), C) ->
|
||||
}
|
||||
}}.
|
||||
|
||||
-spec external_account_set(?DTP('ExternalAccountSetRef'), binary(), ?DTP('CurrencyRef'), ct_helper:config()) ->
|
||||
-spec external_account_set(?DTP('ExternalAccountSetRef'), binary(), ?DTP('CurrencyRef')) ->
|
||||
object().
|
||||
external_account_set(Ref, Name, ?cur(SymCode), C) ->
|
||||
AccountID1 = account(SymCode, C),
|
||||
AccountID2 = account(SymCode, C),
|
||||
external_account_set(Ref, Name, ?cur(SymCode)) ->
|
||||
{ok, AccountID1} = ct_helper:create_account(SymCode),
|
||||
{ok, AccountID2} = ct_helper:create_account(SymCode),
|
||||
{external_account_set, #domain_ExternalAccountSetObject{
|
||||
ref = Ref,
|
||||
data = #domain_ExternalAccountSet{
|
||||
@ -472,21 +472,3 @@ globals(EASRef, PIRefs) ->
|
||||
payment_institutions = ?ordset(PIRefs)
|
||||
}
|
||||
}}.
|
||||
|
||||
-spec account(binary(), ct_helper:config()) -> shumpune_shumpune_thrift:'AccountID'().
|
||||
account(SymCode, C) ->
|
||||
Client = ff_woody_client:new(maps:get('accounter', ct_helper:cfg(services, C))),
|
||||
WoodyCtx = ct_helper:get_woody_ctx(C),
|
||||
Prototype = #shumpune_AccountPrototype{
|
||||
currency_sym_code = SymCode,
|
||||
description = <<>>,
|
||||
creation_time = timestamp()
|
||||
},
|
||||
Request = {{shumpune_shumpune_thrift, 'Accounter'}, 'CreateAccount', {Prototype}},
|
||||
case woody_client:call(Request, Client, WoodyCtx) of
|
||||
{ok, ID} ->
|
||||
ID
|
||||
end.
|
||||
|
||||
timestamp() ->
|
||||
genlib_rfc3339:format(genlib_time:daytime_to_unixtime(calendar:universal_time()), second).
|
||||
|
@ -23,6 +23,8 @@
|
||||
-export([await/2]).
|
||||
-export([await/3]).
|
||||
|
||||
-export([create_account/1]).
|
||||
|
||||
-type test_case_name() :: atom().
|
||||
-type group_name() :: atom().
|
||||
-type config() :: [{atom(), term()}].
|
||||
@ -245,3 +247,10 @@ await(Expect, Compute, Retry0) ->
|
||||
error({'await failed', NotYet})
|
||||
end
|
||||
end.
|
||||
|
||||
-spec create_account(dmsl_accounter_thrift:'PlanID'()) ->
|
||||
{ok, ff_account:accounter_account_id()}
|
||||
| {error, {exception, any()}}.
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
ff_accounting:create_account(CurrencyCode, Description).
|
||||
|
@ -61,7 +61,7 @@ do_setup(Options0, C0) ->
|
||||
{ok, Processing0} = start_processing_apps(Options),
|
||||
C1 = ct_helper:makeup_cfg([ct_helper:woody_ctx()], [{services, services(Options)} | C0]),
|
||||
ok = ct_helper:set_context(C1),
|
||||
ok = setup_dominant(Options, C1),
|
||||
ok = setup_dominant(Options),
|
||||
ok = configure_processing_apps(Options),
|
||||
ok = ct_helper:unset_context(),
|
||||
[{payment_system, Processing0} | C1].
|
||||
@ -136,8 +136,8 @@ start_optional_apps(#{optional_apps := Apps}) ->
|
||||
start_optional_apps(_) ->
|
||||
[].
|
||||
|
||||
setup_dominant(Options, C) ->
|
||||
DomainConfig = domain_config(Options, C),
|
||||
setup_dominant(Options) ->
|
||||
DomainConfig = domain_config(Options),
|
||||
_ = ct_domain_config:upsert(DomainConfig),
|
||||
ok.
|
||||
|
||||
@ -229,7 +229,7 @@ services(Options) ->
|
||||
ff_withdrawal_adapter_host => "http://fistful-server:8022/v1/ff_withdrawal_adapter_host",
|
||||
eventsink => "http://machinegun:8022/v1/event_sink",
|
||||
automaton => "http://machinegun:8022/v1/automaton",
|
||||
accounter => "http://shumway:8022/shumpune",
|
||||
accounter => "http://shumway:8022/accounter",
|
||||
partymgmt => "http://party-management:8022/v1/processing/partymgmt",
|
||||
binbase => "http://localhost:8222/binbase"
|
||||
},
|
||||
@ -251,7 +251,7 @@ dummy_payment_inst_identity_id(Options) ->
|
||||
dummy_provider_identity_id(Options) ->
|
||||
maps:get(dummy_provider_identity_id, Options).
|
||||
|
||||
domain_config(Options, C) ->
|
||||
domain_config(Options) ->
|
||||
WithdrawalDecision1 =
|
||||
{delegates, [
|
||||
delegate(condition(party, <<"12345">>), ?ruleset(2)),
|
||||
@ -279,7 +279,7 @@ domain_config(Options, C) ->
|
||||
|
||||
Default = [
|
||||
ct_domain:globals(?eas(1), [?payinst(1)]),
|
||||
ct_domain:external_account_set(?eas(1), <<"Default">>, ?cur(<<"RUB">>), C),
|
||||
ct_domain:external_account_set(?eas(1), <<"Default">>, ?cur(<<"RUB">>)),
|
||||
|
||||
routing_ruleset(?ruleset(1), <<"WithdrawalRuleset#1">>, WithdrawalDecision1),
|
||||
routing_ruleset(?ruleset(2), <<"WithdrawalRuleset#2">>, WithdrawalDecision2),
|
||||
@ -553,7 +553,7 @@ domain_config(Options, C) ->
|
||||
}
|
||||
}},
|
||||
|
||||
ct_domain:system_account_set(?sas(1), <<"System">>, ?cur(<<"RUB">>), C),
|
||||
ct_domain:system_account_set(?sas(1), <<"System">>, ?cur(<<"RUB">>)),
|
||||
|
||||
ct_domain:inspector(?insp(1), <<"Low Life">>, ?prx(1), #{<<"risk_score">> => <<"low">>}),
|
||||
ct_domain:proxy(?prx(1), <<"Inspector proxy">>),
|
||||
@ -563,19 +563,19 @@ domain_config(Options, C) ->
|
||||
ct_domain:proxy(?prx(7), <<"Another down proxy">>, <<"http://localhost:8222/downbank2">>),
|
||||
ct_domain:proxy(?prx(8), <<"Sleep proxy">>, <<"http://localhost:8222/sleepybank">>),
|
||||
|
||||
ct_domain:withdrawal_provider(?prv(1), ?prx(2), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(2), ?prx(2), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(3), ?prx(3), dummy_provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(4), ?prx(6), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(5), ?prx(2), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(6), ?prx(6), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(7), ?prx(6), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(8), ?prx(2), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(9), ?prx(7), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(10), ?prx(6), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(11), ?prx(8), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(16), ?prx(2), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(17), ?prx(2), provider_identity_id(Options), C),
|
||||
ct_domain:withdrawal_provider(?prv(1), ?prx(2), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(2), ?prx(2), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(3), ?prx(3), dummy_provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(4), ?prx(6), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(5), ?prx(2), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(6), ?prx(6), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(7), ?prx(6), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(8), ?prx(2), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(9), ?prx(7), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(10), ?prx(6), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(11), ?prx(8), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(16), ?prx(2), provider_identity_id(Options)),
|
||||
ct_domain:withdrawal_provider(?prv(17), ?prx(2), provider_identity_id(Options)),
|
||||
|
||||
ct_domain:contract_template(?tmpl(1), ?trms(1)),
|
||||
ct_domain:term_set_hierarchy(?trms(1), [ct_domain:timed_term_set(default_termset(Options))]),
|
||||
|
@ -3,7 +3,6 @@
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
|
||||
-include_lib("fistful_proto/include/ff_proto_deposit_thrift.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
%% Common test API
|
||||
|
||||
@ -718,17 +717,8 @@ get_wallet_balance(ID) ->
|
||||
{ok, Machine} = ff_wallet_machine:get(ID),
|
||||
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
|
||||
|
||||
%% NOTE: This function can flap tests after switch to shumpune
|
||||
%% because of potentially wrong Clock. In common case it should be passed
|
||||
%% from caller after applying changes to account balance.
|
||||
%% This will work fine with shumway because it return LatestClock on any
|
||||
%% balance changes, therefore it will broke tests with shumpune
|
||||
%% because of proper clocks.
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
generate_id() ->
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("fistful_proto/include/ff_proto_w2w_transfer_thrift.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
-export([all/0]).
|
||||
-export([groups/0]).
|
||||
@ -307,10 +306,7 @@ get_wallet_balance(ID) ->
|
||||
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
set_wallet_balance({Amount, Currency}, ID) ->
|
||||
@ -319,31 +315,12 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AnotherAccounterID, AccounterID, {Amount - CurrentAmount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
||||
create_identity(Party, C) ->
|
||||
create_identity(Party, <<"good-two">>, C).
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
|
||||
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
-export([all/0]).
|
||||
-export([groups/0]).
|
||||
@ -642,10 +641,7 @@ get_wallet_balance(ID) ->
|
||||
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
generate_id() ->
|
||||
@ -708,31 +704,12 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AnotherAccounterID, AccounterID, {Amount - CurrentAmount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
||||
make_cash({Amount, Currency}) ->
|
||||
#'fistful_base_Cash'{
|
||||
amount = Amount,
|
||||
|
@ -40,7 +40,7 @@
|
||||
-type identdoc_token() ::
|
||||
binary().
|
||||
|
||||
-type cash() :: ff_transaction:body().
|
||||
-type cash() :: ff_accounting:body().
|
||||
|
||||
-type withdrawal() :: #{
|
||||
id => binary(),
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
-type params() :: #{
|
||||
id := id(),
|
||||
body := ff_transaction:body(),
|
||||
body := ff_accounting:body(),
|
||||
source_id := ff_source:id(),
|
||||
wallet_id := ff_wallet:id(),
|
||||
external_id => external_id()
|
||||
@ -191,7 +191,7 @@
|
||||
-type wallet() :: ff_wallet:wallet_state().
|
||||
-type revert() :: ff_deposit_revert:revert().
|
||||
-type revert_id() :: ff_deposit_revert:id().
|
||||
-type body() :: ff_transaction:body().
|
||||
-type body() :: ff_accounting:body().
|
||||
-type cash() :: ff_cash:cash().
|
||||
-type cash_range() :: ff_range:range(cash()).
|
||||
-type action() :: machinery:action() | undefined.
|
||||
@ -209,7 +209,6 @@
|
||||
-type domain_revision() :: ff_domain_config:revision().
|
||||
-type identity() :: ff_identity:identity_state().
|
||||
-type terms() :: ff_party:terms().
|
||||
-type clock() :: ff_transaction:clock().
|
||||
-type metadata() :: ff_entity_context:md().
|
||||
|
||||
-type transfer_params() :: #{
|
||||
@ -563,9 +562,8 @@ process_limit_check(Deposit) ->
|
||||
domain_revision => DomainRevision,
|
||||
varset => Varset
|
||||
}),
|
||||
Clock = ff_postings_transfer:clock(p_transfer(Deposit)),
|
||||
Events =
|
||||
case validate_wallet_limits(Terms, Wallet, Clock) of
|
||||
case validate_wallet_limits(Terms, Wallet) of
|
||||
{ok, valid} ->
|
||||
[{limit_check, {wallet_receiver, ok}}];
|
||||
{error, {terms_violation, {wallet_limit, {cash_range, {Cash, Range}}}}} ->
|
||||
@ -746,11 +744,11 @@ is_limit_check_ok({wallet_receiver, ok}) ->
|
||||
is_limit_check_ok({wallet_receiver, {failed, _Details}}) ->
|
||||
false.
|
||||
|
||||
-spec validate_wallet_limits(terms(), wallet(), clock()) ->
|
||||
-spec validate_wallet_limits(terms(), wallet()) ->
|
||||
{ok, valid}
|
||||
| {error, {terms_violation, {wallet_limit, {cash_range, {cash(), cash_range()}}}}}.
|
||||
validate_wallet_limits(Terms, Wallet, Clock) ->
|
||||
case ff_party:validate_wallet_limits(Terms, Wallet, Clock) of
|
||||
validate_wallet_limits(Terms, Wallet) ->
|
||||
case ff_party:validate_wallet_limits(Terms, Wallet) of
|
||||
{ok, valid} = Result ->
|
||||
Result;
|
||||
{error, {terms_violation, {cash_range, {Cash, CashRange}}}} ->
|
||||
|
@ -134,7 +134,7 @@
|
||||
-type wallet() :: ff_wallet:wallet_state().
|
||||
-type source_id() :: ff_source:id().
|
||||
-type p_transfer() :: ff_postings_transfer:transfer().
|
||||
-type body() :: ff_transaction:body().
|
||||
-type body() :: ff_accounting:body().
|
||||
-type action() :: machinery:action() | undefined.
|
||||
-type process_result() :: {action(), [event()]}.
|
||||
-type legacy_event() :: any().
|
||||
@ -150,7 +150,6 @@
|
||||
-type domain_revision() :: ff_domain_config:revision().
|
||||
-type identity() :: ff_identity:identity_state().
|
||||
-type terms() :: ff_party:terms().
|
||||
-type clock() :: ff_transaction:clock().
|
||||
|
||||
-type wrapped_adjustment_event() :: ff_adjustment_utils:wrapped_event().
|
||||
|
||||
@ -425,9 +424,8 @@ process_limit_check(Revert) ->
|
||||
varset => Varset
|
||||
}),
|
||||
|
||||
Clock = ff_postings_transfer:clock(p_transfer(Revert)),
|
||||
Events =
|
||||
case validate_wallet_limits(Terms, Wallet, Clock) of
|
||||
case validate_wallet_limits(Terms, Wallet) of
|
||||
{ok, valid} ->
|
||||
[{limit_check, {wallet_receiver, ok}}];
|
||||
{error, {terms_violation, {wallet_limit, {cash_range, {Cash, Range}}}}} ->
|
||||
@ -688,11 +686,11 @@ is_limit_check_ok({wallet_receiver, ok}) ->
|
||||
is_limit_check_ok({wallet_receiver, {failed, _Details}}) ->
|
||||
false.
|
||||
|
||||
-spec validate_wallet_limits(terms(), wallet(), clock()) ->
|
||||
-spec validate_wallet_limits(terms(), wallet()) ->
|
||||
{ok, valid}
|
||||
| {error, validation_error()}.
|
||||
validate_wallet_limits(Terms, Wallet, Clock) ->
|
||||
case ff_party:validate_wallet_limits(Terms, Wallet, Clock) of
|
||||
validate_wallet_limits(Terms, Wallet) ->
|
||||
case ff_party:validate_wallet_limits(Terms, Wallet) of
|
||||
{ok, valid} = Result ->
|
||||
Result;
|
||||
{error, {terms_violation, {cash_range, {Cash, CashRange}}}} ->
|
||||
|
@ -8,7 +8,6 @@
|
||||
-include_lib("damsel/include/dmsl_withdrawals_provider_adapter_thrift.hrl").
|
||||
|
||||
-type id() :: binary().
|
||||
-type clock() :: ff_transaction:clock().
|
||||
|
||||
-define(ACTUAL_FORMAT_VERSION, 4).
|
||||
|
||||
@ -86,7 +85,7 @@
|
||||
wallet_id := ff_wallet_machine:id(),
|
||||
currency_from := ff_currency:id(),
|
||||
currency_to := ff_currency:id(),
|
||||
body := ff_transaction:body(),
|
||||
body := ff_accounting:body(),
|
||||
destination_id => ff_destination:id(),
|
||||
external_id => id()
|
||||
}.
|
||||
@ -239,7 +238,7 @@
|
||||
|
||||
%% Internal types
|
||||
|
||||
-type body() :: ff_transaction:body().
|
||||
-type body() :: ff_accounting:body().
|
||||
-type identity() :: ff_identity:identity_state().
|
||||
-type party_id() :: ff_party:id().
|
||||
-type wallet_id() :: ff_wallet:id().
|
||||
@ -844,9 +843,8 @@ process_limit_check(Withdrawal) ->
|
||||
domain_revision => DomainRevision,
|
||||
varset => build_party_varset(VarsetParams)
|
||||
}),
|
||||
Clock = ff_postings_transfer:clock(p_transfer(Withdrawal)),
|
||||
Events =
|
||||
case validate_wallet_limits(Terms, Wallet, Clock) of
|
||||
case validate_wallet_limits(Terms, Wallet) of
|
||||
{ok, valid} ->
|
||||
[{limit_check, {wallet_sender, ok}}];
|
||||
{error, {terms_violation, {wallet_limit, {cash_range, {Cash, Range}}}}} ->
|
||||
@ -1456,11 +1454,11 @@ is_limit_check_ok({wallet_sender, ok}) ->
|
||||
is_limit_check_ok({wallet_sender, {failed, _Details}}) ->
|
||||
false.
|
||||
|
||||
-spec validate_wallet_limits(terms(), wallet(), clock()) ->
|
||||
-spec validate_wallet_limits(terms(), wallet()) ->
|
||||
{ok, valid}
|
||||
| {error, {terms_violation, {wallet_limit, {cash_range, {cash(), cash_range()}}}}}.
|
||||
validate_wallet_limits(Terms, Wallet, Clock) ->
|
||||
case ff_party:validate_wallet_limits(Terms, Wallet, Clock) of
|
||||
validate_wallet_limits(Terms, Wallet) ->
|
||||
case ff_party:validate_wallet_limits(Terms, Wallet) of
|
||||
{ok, valid} = Result ->
|
||||
Result;
|
||||
{error, {terms_violation, {cash_range, {Cash, CashRange}}}} ->
|
||||
|
@ -78,7 +78,7 @@
|
||||
|
||||
-type data() :: #{
|
||||
id := id(),
|
||||
cash := ff_transaction:body(),
|
||||
cash := ff_accounting:body(),
|
||||
sender := ff_identity:identity_state(),
|
||||
receiver := ff_identity:identity_state(),
|
||||
quote_data => ff_adapter_withdrawal:quote_data()
|
||||
|
@ -321,17 +321,8 @@ get_wallet_balance(ID) ->
|
||||
{ok, Machine} = ff_wallet_machine:get(ID),
|
||||
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
|
||||
|
||||
%% NOTE: This function can flap tests after switch to shumpune
|
||||
%% because of potentially wrong Clock. In common case it should be passed
|
||||
%% from caller after applying changes to account balance.
|
||||
%% This will work fine with shumway because it return LatestClock on any
|
||||
%% balance changes, therefore it will broke tests with shumpune
|
||||
%% because of proper clocks.
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
generate_id() ->
|
||||
|
@ -432,10 +432,7 @@ get_source_balance(ID) ->
|
||||
get_account_balance(ff_source:account(Source)).
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
generate_id() ->
|
||||
|
@ -1,7 +1,6 @@
|
||||
-module(ff_deposit_revert_SUITE).
|
||||
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
%% Common test API
|
||||
|
||||
@ -435,17 +434,14 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AccounterID, AnotherAccounterID, {CurrentAmount - Amount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
generate_id() ->
|
||||
@ -465,22 +461,3 @@ create_source(IID, _C) ->
|
||||
end
|
||||
),
|
||||
ID.
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
@ -1,7 +1,6 @@
|
||||
-module(ff_deposit_revert_adjustment_SUITE).
|
||||
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
%% Common test API
|
||||
|
||||
@ -484,17 +483,14 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AccounterID, AnotherAccounterID, {CurrentAmount - Amount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
generate_id() ->
|
||||
@ -514,22 +510,3 @@ create_source(IID, _C) ->
|
||||
end
|
||||
),
|
||||
ID.
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
@ -444,10 +444,7 @@ get_destination_balance(ID) ->
|
||||
get_account_balance(ff_destination:account(Destination)).
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
create_source(IdentityID, Name, Currency, Resource) ->
|
||||
|
@ -5,7 +5,6 @@
|
||||
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
|
||||
-include_lib("fistful_proto/include/ff_proto_withdrawal_session_thrift.hrl").
|
||||
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
%% Common test API
|
||||
|
||||
@ -897,10 +896,7 @@ get_wallet_balance(ID) ->
|
||||
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
generate_id() ->
|
||||
@ -984,31 +980,12 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AnotherAccounterID, AccounterID, {Amount - CurrentAmount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
||||
make_dummy_party_change(PartyID) ->
|
||||
{ok, _ContractID} = ff_party:create_contract(PartyID, #{
|
||||
payinst => #domain_PaymentInstitutionRef{id = 1},
|
||||
|
@ -1,7 +1,6 @@
|
||||
-module(ff_withdrawal_adjustment_SUITE).
|
||||
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
%% Common test API
|
||||
|
||||
@ -434,10 +433,7 @@ get_destination_balance(ID) ->
|
||||
get_account_balance(ff_destination:account(Destination)).
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
generate_id() ->
|
||||
@ -464,27 +460,8 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AnotherAccounterID, AccounterID, {Amount - CurrentAmount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
%% Common test API
|
||||
|
||||
@ -332,10 +331,7 @@ get_wallet_balance(ID) ->
|
||||
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
create_destination(IID, Currency, C) ->
|
||||
@ -364,27 +360,8 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AnotherAccounterID, AccounterID, {Amount - CurrentAmount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
@ -9,10 +9,10 @@
|
||||
|
||||
-module(ff_account).
|
||||
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
-include_lib("damsel/include/dmsl_accounter_thrift.hrl").
|
||||
|
||||
-type id() :: binary().
|
||||
-type accounter_account_id() :: shumpune_shumpune_thrift:'AccountID'().
|
||||
-type accounter_account_id() :: dmsl_accounter_thrift:'AccountID'().
|
||||
-type account() :: #{
|
||||
id := id(),
|
||||
identity := identity_id(),
|
||||
@ -104,7 +104,9 @@ create(ID, Identity, Currency) ->
|
||||
}),
|
||||
CurrencyID = ff_currency:id(Currency),
|
||||
valid = unwrap(terms, ff_party:validate_account_creation(Terms, CurrencyID)),
|
||||
{ok, AccounterID} = create_account(ID, Currency),
|
||||
CurrencyCode = ff_currency:symcode(Currency),
|
||||
Description = ff_string:join($/, [<<"ff/account">>, ID]),
|
||||
{ok, AccounterID} = ff_accounting:create_account(CurrencyCode, Description),
|
||||
[
|
||||
{created, #{
|
||||
id => ID,
|
||||
@ -133,28 +135,3 @@ get_identity(Account) ->
|
||||
-spec apply_event(event(), ff_maybe:maybe(account())) -> account().
|
||||
apply_event({created, Account}, undefined) ->
|
||||
Account.
|
||||
|
||||
%% Accounter client
|
||||
|
||||
-spec create_account(id(), currency()) ->
|
||||
{ok, accounter_account_id()}
|
||||
| {error, {exception, any()}}.
|
||||
create_account(ID, Currency) ->
|
||||
CurrencyCode = ff_currency:symcode(Currency),
|
||||
Description = ff_string:join($/, [<<"ff/account">>, ID]),
|
||||
case call_accounter('CreateAccount', {construct_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}).
|
||||
|
@ -1,111 +1,118 @@
|
||||
%%%
|
||||
%%% Financial transaction between accounts
|
||||
%%%
|
||||
%%% - Rename to `ff_posting_plan`?
|
||||
%%%
|
||||
-module(ff_accounting).
|
||||
|
||||
-module(ff_transaction).
|
||||
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
-include_lib("damsel/include/dmsl_accounter_thrift.hrl").
|
||||
|
||||
%%
|
||||
|
||||
-type id() :: shumpune_shumpune_thrift:'PlanID'().
|
||||
-type id() :: dmsl_accounter_thrift:'PlanID'().
|
||||
-type account() :: ff_account:account().
|
||||
-type account_id() :: ff_account:accounter_account_id().
|
||||
-type clock() :: ff_clock:clock().
|
||||
-type currency_code() :: dmsl_domain_thrift:'CurrencySymbolicCode'().
|
||||
-type amount() :: dmsl_domain_thrift:'Amount'().
|
||||
-type body() :: ff_cash:cash().
|
||||
-type posting() :: {account_id(), account_id(), body()}.
|
||||
-type balance() :: {ff_indef:indef(amount()), ff_currency:id()}.
|
||||
-type posting_plan_log() :: dmsl_accounter_thrift:'PostingPlanLog'().
|
||||
|
||||
-export_type([id/0]).
|
||||
-export_type([body/0]).
|
||||
-export_type([account/0]).
|
||||
-export_type([posting/0]).
|
||||
-export_type([clock/0]).
|
||||
|
||||
%% TODO
|
||||
%% - Module name is misleading then
|
||||
-export([balance/2]).
|
||||
-export([balance/1]).
|
||||
-export([create_account/2]).
|
||||
|
||||
-export([prepare/2]).
|
||||
-export([commit/2]).
|
||||
-export([cancel/2]).
|
||||
-export([prepare_trx/2]).
|
||||
-export([commit_trx/2]).
|
||||
-export([cancel_trx/2]).
|
||||
|
||||
%%
|
||||
|
||||
-spec balance(account(), clock()) -> {ok, balance()}.
|
||||
balance(Account, Clock) ->
|
||||
-spec balance(account()) -> {ok, balance()}.
|
||||
balance(Account) ->
|
||||
AccountID = ff_account:accounter_account_id(Account),
|
||||
Currency = ff_account:currency(Account),
|
||||
{ok, Balance} = get_balance_by_id(AccountID, Clock),
|
||||
{ok, build_account_balance(Balance, Currency)}.
|
||||
{ok, ThriftAccount} = get_account_by_id(AccountID),
|
||||
{ok, build_account_balance(ThriftAccount, Currency)}.
|
||||
|
||||
-spec prepare(id(), [posting()]) -> {ok, clock()}.
|
||||
prepare(ID, Postings) ->
|
||||
-spec create_account(currency_code(), binary() | undefined) ->
|
||||
{ok, account_id()}
|
||||
| {error, {exception, any()}}.
|
||||
create_account(CurrencyCode, Description) ->
|
||||
case call('CreateAccount', {construct_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
-spec prepare_trx(id(), [posting()]) -> {ok, posting_plan_log()}.
|
||||
prepare_trx(ID, Postings) ->
|
||||
hold(encode_plan_change(ID, Postings)).
|
||||
|
||||
-spec commit(id(), [posting()]) -> {ok, clock()}.
|
||||
commit(ID, Postings) ->
|
||||
-spec commit_trx(id(), [posting()]) -> {ok, posting_plan_log()}.
|
||||
commit_trx(ID, Postings) ->
|
||||
commit_plan(encode_plan(ID, Postings)).
|
||||
|
||||
-spec cancel(id(), [posting()]) -> {ok, clock()}.
|
||||
cancel(ID, Postings) ->
|
||||
-spec cancel_trx(id(), [posting()]) -> {ok, posting_plan_log()}.
|
||||
cancel_trx(ID, Postings) ->
|
||||
rollback_plan(encode_plan(ID, Postings)).
|
||||
|
||||
%% Woody stuff
|
||||
|
||||
get_balance_by_id(ID, Clock) ->
|
||||
case call('GetBalanceByID', {ID, ff_clock:marshal(shumpune, Clock)}) of
|
||||
{ok, Balance} ->
|
||||
{ok, Balance};
|
||||
get_account_by_id(ID) ->
|
||||
case call('GetAccountByID', {ID}) of
|
||||
{ok, Account} ->
|
||||
{ok, Account};
|
||||
{exception, Unexpected} ->
|
||||
error(Unexpected)
|
||||
end.
|
||||
|
||||
hold(PlanChange) ->
|
||||
case call('Hold', {PlanChange}) of
|
||||
{ok, Clock} ->
|
||||
{ok, ff_clock:unmarshal(shumpune, Clock)};
|
||||
{ok, PostingPlanLog} ->
|
||||
{ok, PostingPlanLog};
|
||||
{exception, Unexpected} ->
|
||||
error(Unexpected)
|
||||
end.
|
||||
|
||||
commit_plan(Plan) ->
|
||||
case call('CommitPlan', {Plan}) of
|
||||
{ok, Clock} ->
|
||||
{ok, ff_clock:unmarshal(shumpune, Clock)};
|
||||
{ok, PostingPlanLog} ->
|
||||
{ok, PostingPlanLog};
|
||||
{exception, Unexpected} ->
|
||||
error(Unexpected)
|
||||
end.
|
||||
|
||||
rollback_plan(Plan) ->
|
||||
case call('RollbackPlan', {Plan}) of
|
||||
{ok, Clock} ->
|
||||
{ok, ff_clock:unmarshal(shumpune, Clock)};
|
||||
{ok, PostingPlanLog} ->
|
||||
{ok, PostingPlanLog};
|
||||
{exception, Unexpected} ->
|
||||
error(Unexpected)
|
||||
end.
|
||||
|
||||
call(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
Service = {dmsl_accounter_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}).
|
||||
|
||||
encode_plan_change(ID, Postings) ->
|
||||
#shumpune_PostingPlanChange{
|
||||
#accounter_PostingPlanChange{
|
||||
id = ID,
|
||||
batch = encode_batch(Postings)
|
||||
}.
|
||||
|
||||
encode_plan(ID, Postings) ->
|
||||
#shumpune_PostingPlan{
|
||||
#accounter_PostingPlan{
|
||||
id = ID,
|
||||
batch_list = [encode_batch(Postings)]
|
||||
}.
|
||||
|
||||
encode_batch(Postings) ->
|
||||
#shumpune_PostingBatch{
|
||||
#accounter_PostingBatch{
|
||||
% TODO
|
||||
id = 1,
|
||||
postings = [
|
||||
@ -115,7 +122,7 @@ encode_batch(Postings) ->
|
||||
}.
|
||||
|
||||
encode_posting(Source, Destination, {Amount, Currency}) ->
|
||||
#shumpune_Posting{
|
||||
#accounter_Posting{
|
||||
from_id = Source,
|
||||
to_id = Destination,
|
||||
amount = Amount,
|
||||
@ -124,7 +131,7 @@ encode_posting(Source, Destination, {Amount, Currency}) ->
|
||||
}.
|
||||
|
||||
build_account_balance(
|
||||
#shumpune_Balance{
|
||||
#accounter_Account{
|
||||
own_amount = Own,
|
||||
max_available_amount = MaxAvail,
|
||||
min_available_amount = MinAvail
|
||||
@ -132,3 +139,9 @@ build_account_balance(
|
||||
Currency
|
||||
) ->
|
||||
{ff_indef:new(MinAvail, Own, MaxAvail), Currency}.
|
||||
|
||||
construct_prototype(CurrencyCode, Description) ->
|
||||
#accounter_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
@ -108,7 +108,7 @@
|
||||
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]).
|
||||
|
||||
%% Internal types
|
||||
-type cash() :: ff_transaction:body().
|
||||
-type cash() :: ff_accounting:body().
|
||||
-type account() :: ff_account:account().
|
||||
|
||||
-type finalize_error() :: {postings, posting_finalize_error()}.
|
||||
|
@ -1,7 +1,6 @@
|
||||
-module(ff_clock).
|
||||
|
||||
-include_lib("fistful_proto/include/ff_proto_transfer_thrift.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
-define(VERSION, 1).
|
||||
-define(TYPE_LATEST, latest).
|
||||
@ -9,7 +8,7 @@
|
||||
|
||||
-type type() :: ?TYPE_LATEST | ?TYPE_VECTOR.
|
||||
-type version() :: non_neg_integer().
|
||||
-type kind() :: transfer | shumpune.
|
||||
-type kind() :: transfer.
|
||||
|
||||
-opaque clock() :: #{
|
||||
version := version(),
|
||||
@ -31,31 +30,17 @@ latest_clock() ->
|
||||
new(?TYPE_LATEST).
|
||||
|
||||
-spec marshal(kind(), clock()) ->
|
||||
ff_proto_transfer_thrift:'Clock'()
|
||||
| shumpune_shumpune_thrift:'Clock'().
|
||||
ff_proto_transfer_thrift:'Clock'().
|
||||
marshal(transfer, #{type := ?TYPE_LATEST = Type}) ->
|
||||
{Type, #transfer_LatestClock{}};
|
||||
marshal(transfer, #{type := ?TYPE_VECTOR = Type, state := State}) ->
|
||||
{Type, #transfer_VectorClock{state = State}};
|
||||
marshal(shumpune, #{type := ?TYPE_LATEST = Type}) ->
|
||||
{Type, #shumpune_LatestClock{}};
|
||||
marshal(shumpune, #{type := ?TYPE_VECTOR = Type, state := State}) ->
|
||||
{Type, #shumpune_VectorClock{state = State}}.
|
||||
{Type, #transfer_VectorClock{state = State}}.
|
||||
|
||||
-spec unmarshal(kind(), Clock) -> clock() when
|
||||
Clock ::
|
||||
ff_proto_transfer_thrift:'Clock'()
|
||||
| shumpune_shumpune_thrift:'Clock'().
|
||||
Clock :: ff_proto_transfer_thrift:'Clock'().
|
||||
unmarshal(transfer, {?TYPE_LATEST = Type, #transfer_LatestClock{}}) ->
|
||||
new(Type);
|
||||
unmarshal(transfer, {?TYPE_VECTOR = Type, #transfer_VectorClock{state = State}}) ->
|
||||
Clock = new(Type),
|
||||
Clock#{
|
||||
state => State
|
||||
};
|
||||
unmarshal(shumpune, {?TYPE_LATEST = Type, #shumpune_LatestClock{}}) ->
|
||||
new(Type);
|
||||
unmarshal(shumpune, {?TYPE_VECTOR = Type, #shumpune_VectorClock{state = State}}) ->
|
||||
Clock = new(Type),
|
||||
Clock#{
|
||||
state => State
|
||||
|
@ -13,7 +13,6 @@
|
||||
-type id() :: dmsl_domain_thrift:'PartyID'().
|
||||
-type contract_id() :: dmsl_domain_thrift:'ContractID'().
|
||||
-type wallet_id() :: dmsl_domain_thrift:'WalletID'().
|
||||
-type clock() :: ff_transaction:clock().
|
||||
-type revision() :: dmsl_domain_thrift:'PartyRevision'().
|
||||
-type terms() :: dmsl_domain_thrift:'TermSet'().
|
||||
-type attempt_limit() :: integer().
|
||||
@ -84,7 +83,7 @@
|
||||
-export([validate_withdrawal_creation/3]).
|
||||
-export([validate_deposit_creation/2]).
|
||||
-export([validate_w2w_transfer_creation/2]).
|
||||
-export([validate_wallet_limits/3]).
|
||||
-export([validate_wallet_limits/2]).
|
||||
-export([get_contract_terms/6]).
|
||||
-export([compute_payment_institution/3]).
|
||||
-export([compute_routing_ruleset/3]).
|
||||
@ -725,11 +724,11 @@ validate_wallet_terms_currency(CurrencyID, Terms) ->
|
||||
} = Terms,
|
||||
validate_currency(CurrencyID, Currencies).
|
||||
|
||||
-spec validate_wallet_limits(terms(), wallet(), clock()) ->
|
||||
-spec validate_wallet_limits(terms(), wallet()) ->
|
||||
{ok, valid}
|
||||
| {error, invalid_wallet_terms_error()}
|
||||
| {error, cash_range_validation_error()}.
|
||||
validate_wallet_limits(Terms, Wallet, Clock) ->
|
||||
validate_wallet_limits(Terms, Wallet) ->
|
||||
do(fun() ->
|
||||
#domain_TermSet{wallets = WalletTerms} = Terms,
|
||||
valid = unwrap(validate_wallet_limits_terms_is_reduced(WalletTerms)),
|
||||
@ -737,7 +736,7 @@ validate_wallet_limits(Terms, Wallet, Clock) ->
|
||||
wallet_limit = {value, CashRange}
|
||||
} = WalletTerms,
|
||||
Account = ff_wallet:account(Wallet),
|
||||
valid = unwrap(validate_account_balance(Account, CashRange, Clock))
|
||||
valid = unwrap(validate_account_balance(Account, CashRange))
|
||||
end).
|
||||
|
||||
-spec validate_wallet_limits_terms_is_reduced(wallet_terms()) -> {ok, valid} | {error, {invalid_terms, _Details}}.
|
||||
@ -826,17 +825,12 @@ validate_currency(CurrencyID, Currencies) ->
|
||||
{error, {terms_violation, {not_allowed_currency, {CurrencyRef, Currencies}}}}
|
||||
end.
|
||||
|
||||
-spec validate_account_balance(ff_account:account(), domain_cash_range(), clock()) ->
|
||||
-spec validate_account_balance(ff_account:account(), domain_cash_range()) ->
|
||||
{ok, valid}
|
||||
| {error, cash_range_validation_error()}.
|
||||
validate_account_balance(Account, CashRange, Clock) ->
|
||||
validate_account_balance(Account, CashRange) ->
|
||||
do(fun() ->
|
||||
{Amounts, CurrencyID} = unwrap(
|
||||
ff_transaction:balance(
|
||||
Account,
|
||||
Clock
|
||||
)
|
||||
),
|
||||
{Amounts, CurrencyID} = unwrap(ff_accounting:balance(Account)),
|
||||
ExpMinCash = ff_dmsl_codec:marshal(cash, {ff_indef:expmin(Amounts), CurrencyID}),
|
||||
ExpMaxCash = ff_dmsl_codec:marshal(cash, {ff_indef:expmax(Amounts), CurrencyID}),
|
||||
valid = unwrap(validate_cash_range(ExpMinCash, CashRange)),
|
||||
|
@ -14,7 +14,6 @@
|
||||
-module(ff_postings_transfer).
|
||||
|
||||
-type final_cash_flow() :: ff_cash_flow:final_cash_flow().
|
||||
-type clock() :: ff_clock:clock().
|
||||
|
||||
-type status() ::
|
||||
created
|
||||
@ -25,13 +24,11 @@
|
||||
-type transfer() :: #{
|
||||
id := id(),
|
||||
final_cash_flow := final_cash_flow(),
|
||||
status => status(),
|
||||
clock => clock()
|
||||
status => status()
|
||||
}.
|
||||
|
||||
-type event() ::
|
||||
{created, transfer()}
|
||||
| {clock_updated, clock()}
|
||||
| {status_changed, status()}.
|
||||
|
||||
-export_type([transfer/0]).
|
||||
@ -42,7 +39,6 @@
|
||||
-export([id/1]).
|
||||
-export([final_cash_flow/1]).
|
||||
-export([status/1]).
|
||||
-export([clock/1]).
|
||||
|
||||
-export([create/2]).
|
||||
-export([prepare/1]).
|
||||
@ -60,7 +56,7 @@
|
||||
|
||||
%% Internal types
|
||||
|
||||
-type id() :: ff_transaction:id().
|
||||
-type id() :: ff_accounting:id().
|
||||
-type account() :: ff_account:account().
|
||||
|
||||
%%
|
||||
@ -68,7 +64,6 @@
|
||||
-spec id(transfer()) -> id().
|
||||
-spec final_cash_flow(transfer()) -> final_cash_flow().
|
||||
-spec status(transfer()) -> status().
|
||||
-spec clock(transfer()) -> clock().
|
||||
|
||||
id(#{id := V}) ->
|
||||
V.
|
||||
@ -79,11 +74,6 @@ final_cash_flow(#{final_cash_flow := V}) ->
|
||||
status(#{status := V}) ->
|
||||
V.
|
||||
|
||||
clock(#{clock := V}) ->
|
||||
V;
|
||||
clock(_) ->
|
||||
ff_clock:latest_clock().
|
||||
|
||||
%%
|
||||
|
||||
-spec create(id(), final_cash_flow()) ->
|
||||
@ -139,8 +129,8 @@ prepare(Transfer = #{status := created}) ->
|
||||
ID = id(Transfer),
|
||||
CashFlow = final_cash_flow(Transfer),
|
||||
do(fun() ->
|
||||
Clock = unwrap(ff_transaction:prepare(ID, construct_trx_postings(CashFlow))),
|
||||
[{clock_updated, Clock}, {status_changed, prepared}]
|
||||
_PostingPlanLog = unwrap(ff_accounting:prepare_trx(ID, construct_trx_postings(CashFlow))),
|
||||
[{status_changed, prepared}]
|
||||
end);
|
||||
prepare(#{status := prepared}) ->
|
||||
{ok, []};
|
||||
@ -160,8 +150,8 @@ commit(Transfer = #{status := prepared}) ->
|
||||
ID = id(Transfer),
|
||||
CashFlow = final_cash_flow(Transfer),
|
||||
do(fun() ->
|
||||
Clock = unwrap(ff_transaction:commit(ID, construct_trx_postings(CashFlow))),
|
||||
[{clock_updated, Clock}, {status_changed, committed}]
|
||||
_PostingPlanLog = unwrap(ff_accounting:commit_trx(ID, construct_trx_postings(CashFlow))),
|
||||
[{status_changed, committed}]
|
||||
end);
|
||||
commit(#{status := committed}) ->
|
||||
{ok, []};
|
||||
@ -177,8 +167,8 @@ cancel(Transfer = #{status := prepared}) ->
|
||||
ID = id(Transfer),
|
||||
CashFlow = final_cash_flow(Transfer),
|
||||
do(fun() ->
|
||||
Clock = unwrap(ff_transaction:cancel(ID, construct_trx_postings(CashFlow))),
|
||||
[{clock_updated, Clock}, {status_changed, cancelled}]
|
||||
_PostingPlanLog = unwrap(ff_accounting:cancel_trx(ID, construct_trx_postings(CashFlow))),
|
||||
[{status_changed, cancelled}]
|
||||
end);
|
||||
cancel(#{status := cancelled}) ->
|
||||
{ok, []};
|
||||
@ -190,18 +180,16 @@ cancel(#{status := Status}) ->
|
||||
-spec apply_event(event(), ff_maybe:maybe(account())) -> account().
|
||||
apply_event({created, Transfer}, undefined) ->
|
||||
Transfer;
|
||||
apply_event({clock_updated, Clock}, Transfer) ->
|
||||
Transfer#{clock => Clock};
|
||||
apply_event({status_changed, S}, Transfer) ->
|
||||
Transfer#{status => S}.
|
||||
|
||||
%%
|
||||
|
||||
-spec construct_trx_postings(final_cash_flow()) -> [ff_transaction:posting()].
|
||||
-spec construct_trx_postings(final_cash_flow()) -> [ff_accounting:posting()].
|
||||
construct_trx_postings(#{postings := Postings}) ->
|
||||
lists:map(fun construct_trx_posting/1, Postings).
|
||||
|
||||
-spec construct_trx_posting(ff_cash_flow:final_posting()) -> ff_transaction:posting().
|
||||
-spec construct_trx_posting(ff_cash_flow:final_posting()) -> ff_accounting:posting().
|
||||
construct_trx_posting(Posting) ->
|
||||
#{
|
||||
sender := #{account := Sender},
|
||||
|
@ -196,7 +196,7 @@ check_accessible(Wallet) ->
|
||||
-spec get_account_balance(wallet_state()) -> {ok, ff_account:account_balance()}.
|
||||
get_account_balance(Wallet) ->
|
||||
Account = ff_wallet:account(Wallet),
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(Account, ff_clock:latest_clock()),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
AccountBalance = #{
|
||||
id => ff_account:id(Account),
|
||||
currency => Currency,
|
||||
|
@ -15,7 +15,6 @@
|
||||
uuid,
|
||||
damsel,
|
||||
dmt_client,
|
||||
shumpune_proto,
|
||||
party_client,
|
||||
binbase_proto
|
||||
]},
|
||||
|
@ -90,7 +90,7 @@ create_ok(C) ->
|
||||
Wallet = ff_wallet_machine:wallet(unwrap(ff_wallet_machine:get(ID))),
|
||||
Accessibility = unwrap(ff_wallet:is_accessible(Wallet)),
|
||||
Account = ff_wallet:account(Wallet),
|
||||
{Amount, <<"RUB">>} = unwrap(ff_transaction:balance(Account, ff_clock:latest_clock())),
|
||||
{Amount, <<"RUB">>} = unwrap(ff_accounting:balance(Account)),
|
||||
CurrentAmount = ff_indef:current(Amount),
|
||||
?assertMatch(ok, CreateResult),
|
||||
?assertMatch(accessible, Accessibility),
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
-type params() :: #{
|
||||
id := id(),
|
||||
body := ff_transaction:body(),
|
||||
body := ff_accounting:body(),
|
||||
wallet_from_id := wallet_id(),
|
||||
wallet_to_id := wallet_id(),
|
||||
external_id => external_id(),
|
||||
@ -160,7 +160,7 @@
|
||||
-type process_result() :: {action(), [event()]}.
|
||||
-type wallet_id() :: ff_wallet:id().
|
||||
-type wallet() :: ff_wallet:wallet_state().
|
||||
-type body() :: ff_transaction:body().
|
||||
-type body() :: ff_accounting:body().
|
||||
-type cash() :: ff_cash:cash().
|
||||
-type cash_range() :: ff_range:range(cash()).
|
||||
-type action() :: machinery:action() | undefined.
|
||||
@ -176,7 +176,6 @@
|
||||
-type domain_revision() :: ff_domain_config:revision().
|
||||
-type identity() :: ff_identity:identity_state().
|
||||
-type terms() :: ff_party:terms().
|
||||
-type clock() :: ff_transaction:clock().
|
||||
-type metadata() :: ff_entity_context:md().
|
||||
|
||||
-type activity() ::
|
||||
@ -615,8 +614,7 @@ process_wallet_limit_check(WalletID, W2WTransferState) ->
|
||||
domain_revision => DomainRevision,
|
||||
varset => Varset
|
||||
}),
|
||||
Clock = ff_postings_transfer:clock(p_transfer(W2WTransferState)),
|
||||
case validate_wallet_limits(Terms, Wallet, Clock) of
|
||||
case validate_wallet_limits(Terms, Wallet) of
|
||||
{ok, valid} ->
|
||||
ok;
|
||||
{error, {terms_violation, {wallet_limit, {cash_range, {Cash, Range}}}}} ->
|
||||
@ -657,11 +655,11 @@ is_limit_check_ok({wallet_sender, {failed, _Details}}) ->
|
||||
is_limit_check_ok({wallet_receiver, {failed, _Details}}) ->
|
||||
false.
|
||||
|
||||
-spec validate_wallet_limits(terms(), wallet(), clock()) ->
|
||||
-spec validate_wallet_limits(terms(), wallet()) ->
|
||||
{ok, valid}
|
||||
| {error, {terms_violation, {wallet_limit, {cash_range, {cash(), cash_range()}}}}}.
|
||||
validate_wallet_limits(Terms, Wallet, Clock) ->
|
||||
case ff_party:validate_wallet_limits(Terms, Wallet, Clock) of
|
||||
validate_wallet_limits(Terms, Wallet) ->
|
||||
case ff_party:validate_wallet_limits(Terms, Wallet) of
|
||||
{ok, valid} = Result ->
|
||||
Result;
|
||||
{error, {terms_violation, {cash_range, {Cash, CashRange}}}} ->
|
||||
|
@ -1,7 +1,6 @@
|
||||
-module(w2w_adjustment_SUITE).
|
||||
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
%% Common test API
|
||||
|
||||
@ -439,10 +438,7 @@ get_wallet_balance(ID) ->
|
||||
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
|
||||
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
set_wallet_balance({Amount, Currency}, ID) ->
|
||||
@ -451,30 +447,11 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AnotherAccounterID, AccounterID, {Amount - CurrentAmount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
generate_id() ->
|
||||
ff_id:generate_snowflake_id().
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
-include_lib("stdlib/include/assert.hrl").
|
||||
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
|
||||
-include_lib("shumpune_proto/include/shumpune_shumpune_thrift.hrl").
|
||||
|
||||
%% Common test API
|
||||
|
||||
@ -338,17 +337,8 @@ get_wallet_balance(ID) ->
|
||||
{ok, Machine} = ff_wallet_machine:get(ID),
|
||||
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
|
||||
|
||||
%% NOTE: This function can flap tests after switch to shumpune
|
||||
%% because of potentially wrong Clock. In common case it should be passed
|
||||
%% from caller after applying changes to account balance.
|
||||
%% This will work fine with shumway because it return LatestClock on any
|
||||
%% balance changes, therefore it will broke tests with shumpune
|
||||
%% because of proper clocks.
|
||||
get_account_balance(Account) ->
|
||||
{ok, {Amounts, Currency}} = ff_transaction:balance(
|
||||
Account,
|
||||
ff_clock:latest_clock()
|
||||
),
|
||||
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
|
||||
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
|
||||
|
||||
set_wallet_balance({Amount, Currency}, ID) ->
|
||||
@ -357,30 +347,11 @@ set_wallet_balance({Amount, Currency}, ID) ->
|
||||
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
|
||||
AccounterID = ff_account:accounter_account_id(Account),
|
||||
{CurrentAmount, _, Currency} = get_account_balance(Account),
|
||||
{ok, AnotherAccounterID} = create_account(Currency),
|
||||
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
|
||||
Postings = [{AnotherAccounterID, AccounterID, {Amount - CurrentAmount, Currency}}],
|
||||
{ok, _} = ff_transaction:prepare(TransactionID, Postings),
|
||||
{ok, _} = ff_transaction:commit(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
|
||||
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
|
||||
ok.
|
||||
|
||||
generate_id() ->
|
||||
ff_id:generate_snowflake_id().
|
||||
|
||||
create_account(CurrencyCode) ->
|
||||
Description = <<"ff_test">>,
|
||||
case call_accounter('CreateAccount', {construct_account_prototype(CurrencyCode, Description)}) of
|
||||
{ok, Result} ->
|
||||
{ok, Result};
|
||||
{exception, Exception} ->
|
||||
{error, {exception, Exception}}
|
||||
end.
|
||||
|
||||
construct_account_prototype(CurrencyCode, Description) ->
|
||||
#shumpune_AccountPrototype{
|
||||
currency_sym_code = CurrencyCode,
|
||||
description = Description
|
||||
}.
|
||||
|
||||
call_accounter(Function, Args) ->
|
||||
Service = {shumpune_shumpune_thrift, 'Accounter'},
|
||||
ff_woody_client:call(accounter, {Service, Function, Args}, woody_context:new()).
|
||||
|
@ -78,7 +78,7 @@
|
||||
{services, #{
|
||||
'eventsink' => "http://machinegun:8022/v1/event_sink",
|
||||
'automaton' => "http://machinegun:8022/v1/automaton",
|
||||
'accounter' => "http://shumway:8022/shumpune"
|
||||
'accounter' => "http://shumway:8022/accounter"
|
||||
}}
|
||||
]},
|
||||
|
||||
|
@ -40,8 +40,7 @@
|
||||
{dmt_client, {git, "https://github.com/valitydev/dmt_client.git", {branch, master}}},
|
||||
{fistful_proto, {git, "https://github.com/valitydev/fistful-proto.git", {branch, "master"}}},
|
||||
{binbase_proto, {git, "https://github.com/valitydev/binbase-proto.git", {branch, "master"}}},
|
||||
{party_client, {git, "https://github.com/valitydev/party_client_erlang.git", {branch, "master"}}},
|
||||
{shumpune_proto, {git, "https://github.com/valitydev/shumaich-proto.git", {ref, "4c87f03"}}}
|
||||
{party_client, {git, "https://github.com/valitydev/party-client-erlang.git", {branch, "master"}}}
|
||||
]}.
|
||||
|
||||
{xref_checks, [
|
||||
|
@ -52,7 +52,7 @@
|
||||
{<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},2},
|
||||
{<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.3.1">>},2},
|
||||
{<<"party_client">>,
|
||||
{git,"https://github.com/valitydev/party_client_erlang.git",
|
||||
{git,"https://github.com/valitydev/party-client-erlang.git",
|
||||
{ref,"8fc5595c4c61c0fe3d2dc29a61f48ba94e9bdef7"}},
|
||||
0},
|
||||
{<<"prometheus">>,{pkg,<<"prometheus">>,<<"4.8.1">>},0},
|
||||
@ -68,10 +68,6 @@
|
||||
{git,"https://github.com/valitydev/scoper.git",
|
||||
{ref,"7f3183df279bc8181efe58dafd9cae164f495e6f"}},
|
||||
0},
|
||||
{<<"shumpune_proto">>,
|
||||
{git,"https://github.com/valitydev/shumaich-proto.git",
|
||||
{ref,"4c87f03591cae3dad41504eb463d962af536b1ab"}},
|
||||
0},
|
||||
{<<"snowflake">>,
|
||||
{git,"https://github.com/valitydev/snowflake.git",
|
||||
{ref,"de159486ef40cec67074afe71882bdc7f7deab72"}},
|
||||
|
Loading…
Reference in New Issue
Block a user