FF-59: respect withdrawal provider's terms (#58)

press "F" to pay respect

* FF-59: respect withdrawal provider's terms
* fix test to proof code validity
This commit is contained in:
Evgeny Levenets 2019-02-08 11:49:15 +03:00 committed by GitHub
parent 27bea54b03
commit 565066f089
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 12 deletions

View File

@ -44,7 +44,7 @@ withdrawal_provider(Ref, ProxyRef, IdentityID, C) ->
proxy = #domain_Proxy{ref = ProxyRef, additional = #{}},
identity = IdentityID,
withdrawal_terms = #domain_WithdrawalProvisionTerms{
currencies = {value, ?ordset([])},
currencies = {value, ?ordset([?cur(<<"RUB">>)])},
payout_methods = {value, ?ordset([])},
cash_limit = {value, ?cashrng(
{inclusive, ?cash( 0, <<"RUB">>)},

View File

@ -240,11 +240,27 @@ create_route(Withdrawal) ->
DestinationMachine = unwrap(destination, ff_destination:get_machine(DestinationID)),
Destination = ff_destination:get(DestinationMachine),
VS = unwrap(collect_varset(Body, Wallet, Destination)),
ProviderID = unwrap(ff_payment_institution:compute_withdrawal_provider(PaymentInstitution, VS)),
Providers = unwrap(ff_payment_institution:compute_withdrawal_providers(PaymentInstitution, VS)),
ProviderID = unwrap(choose_provider(Providers, VS)),
{continue, [{route_changed, #{provider_id => ProviderID}}]}
end).
choose_provider(Providers, VS) ->
case lists:filter(fun(P) -> validate_withdrawals_terms(P, VS) end, Providers) of
[ProviderID | _] ->
{ok, ProviderID};
[] ->
{error, route_not_found}
end.
validate_withdrawals_terms(ID, VS) ->
Provider = unwrap(ff_payouts_provider:get(ID)),
case ff_payouts_provider:validate_terms(Provider, VS) of
{ok, valid} ->
true;
{error, _Error} ->
false
end.
-spec create_p_transfer(withdrawal()) ->
{ok, process_result()} |

View File

@ -28,7 +28,7 @@
-export([ref/1]).
-export([get/1]).
-export([compute_withdrawal_provider/2]).
-export([compute_withdrawal_providers/2]).
-export([compute_system_accounts/2]).
%% Pipeline
@ -59,16 +59,16 @@ get(ID) ->
decode(ID, PaymentInstitution)
end).
-spec compute_withdrawal_provider(payment_institution(), hg_selector:varset()) ->
{ok, ff_payouts_provider:id()} | {error, term()}.
-spec compute_withdrawal_providers(payment_institution(), hg_selector:varset()) ->
{ok, [ff_payouts_provider:id()]} | {error, term()}.
compute_withdrawal_provider(#{providers := ProviderSelector}, VS) ->
do(fun() ->
Providers = unwrap(hg_selector:reduce_to_value(ProviderSelector, VS)),
%% TODO choose wizely one of them
[#domain_WithdrawalProviderRef{id = ProviderID} | _] = Providers,
ProviderID
end).
compute_withdrawal_providers(#{providers := ProviderSelector}, VS) ->
case hg_selector:reduce_to_value(ProviderSelector, VS) of
{ok, Providers} ->
{ok, [ProviderID || #domain_WithdrawalProviderRef{id = ProviderID} <- Providers]};
Error ->
Error
end.
-spec compute_system_accounts(payment_institution(), hg_selector:varset()) ->
{ok, system_accounts()} | {error, term()}.

View File

@ -27,6 +27,7 @@
-export([ref/1]).
-export([get/1]).
-export([compute_fees/2]).
-export([validate_terms/2]).
%% Pipeline
@ -77,8 +78,47 @@ compute_fees(#{withdrawal_terms := WithdrawalTerms}, VS) ->
postings => ff_cash_flow:decode_domain_postings(CashFlow)
}.
-spec validate_terms(withdrawal_provider(), hg_selector:varset()) ->
{ok, valid} |
{error, Error :: term()}.
validate_terms(#{withdrawal_terms := WithdrawalTerms}, VS) ->
#domain_WithdrawalProvisionTerms{
currencies = CurrenciesSelector,
payout_methods = PayoutMethodsSelector,
cash_limit = CashLimitSelector
} = WithdrawalTerms,
do(fun () ->
valid = unwrap(validate_currencies(CurrenciesSelector, VS)),
valid = unwrap(validate_payout_methods(PayoutMethodsSelector, VS)),
valid = unwrap(validate_cash_limit(CashLimitSelector, VS))
end).
%%
validate_currencies(CurrenciesSelector, #{currency := CurrencyRef} = VS) ->
Currencies = unwrap(hg_selector:reduce_to_value(CurrenciesSelector, VS)),
case ordsets:is_element(CurrencyRef, Currencies) of
true ->
{ok, valid};
false ->
{error, {terms_violation, {not_allowed_currency, {CurrencyRef, Currencies}}}}
end.
validate_payout_methods(_, _) ->
%% PayoutMethodsSelector is useless for withdrawals
%% so we can just ignore it
{ok, valid}.
validate_cash_limit(CashLimitSelector, #{cost := Cash} = VS) ->
CashRange = unwrap(hg_selector:reduce_to_value(CashLimitSelector, VS)),
case hg_cash_range:is_inside(Cash, CashRange) of
within ->
{ok, valid};
_NotInRange ->
{error, {terms_violation, {cash_range, {Cash, CashRange}}}}
end.
decode(ID, #domain_WithdrawalProvider{
proxy = Proxy,
identity = Identity,