Make adjustments respect possibly updated merchant terms (#199)

This commit is contained in:
Andrew Mayorov 2018-04-03 20:09:12 +03:00 committed by GitHub
parent 3e283df2cc
commit d069ee9c44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 89 additions and 24 deletions

View File

@ -21,6 +21,8 @@
-type timestamp_interval_bound() :: dmsl_base_thrift:'TimestampIntervalBound'(). -type timestamp_interval_bound() :: dmsl_base_thrift:'TimestampIntervalBound'().
-type time_span() :: dmsl_base_thrift:'TimeSpan'(). -type time_span() :: dmsl_base_thrift:'TimeSpan'().
-export_type([timestamp/0]).
%% %%
-spec format_dt(datetime()) -> timestamp(). -spec format_dt(datetime()) -> timestamp().

View File

@ -86,9 +86,16 @@ get_payment_tags(PaymentSession) ->
-spec get_payment_opts(st()) -> -spec get_payment_opts(st()) ->
hg_invoice_payment:opts(). hg_invoice_payment:opts().
get_payment_opts(St = #st{invoice = Invoice}) -> get_payment_opts(St) ->
get_payment_opts(get_created_at(St), St).
-spec get_payment_opts(hg_datetime:timestamp(), st()) ->
hg_invoice_payment:opts().
get_payment_opts(Timestamp, St = #st{invoice = Invoice}) ->
#{ #{
party => checkout_party(St), % TODO repalce with checkout by revision
party => hg_party_machine:checkout(get_party_id(St), {timestamp, Timestamp}),
invoice => Invoice invoice => Invoice
}. }.
@ -515,27 +522,33 @@ handle_call({refund_payment, PaymentID, Params}, St) ->
handle_call({create_payment_adjustment, PaymentID, Params}, St) -> handle_call({create_payment_adjustment, PaymentID, Params}, St) ->
_ = assert_invoice_accessible(St), _ = assert_invoice_accessible(St),
PaymentSession = get_payment_session(PaymentID, St), PaymentSession = get_payment_session(PaymentID, St),
Timestamp = hg_datetime:format_now(),
PaymentOpts = get_payment_opts(Timestamp, St),
wrap_payment_impact( wrap_payment_impact(
PaymentID, PaymentID,
hg_invoice_payment:create_adjustment(Params, PaymentSession, get_payment_opts(St)), hg_invoice_payment:create_adjustment(Timestamp, Params, PaymentSession, PaymentOpts),
St St
); );
handle_call({capture_payment_adjustment, PaymentID, ID}, St) -> handle_call({capture_payment_adjustment, PaymentID, ID}, St) ->
_ = assert_invoice_accessible(St), _ = assert_invoice_accessible(St),
PaymentSession = get_payment_session(PaymentID, St), PaymentSession = get_payment_session(PaymentID, St),
Adjustment = hg_invoice_payment:get_adjustment(ID, PaymentSession),
PaymentOpts = get_payment_opts(Adjustment#domain_InvoicePaymentAdjustment.created_at, St),
wrap_payment_impact( wrap_payment_impact(
PaymentID, PaymentID,
hg_invoice_payment:capture_adjustment(ID, PaymentSession, get_payment_opts(St)), hg_invoice_payment:capture_adjustment(ID, PaymentSession, PaymentOpts),
St St
); );
handle_call({cancel_payment_adjustment, PaymentID, ID}, St) -> handle_call({cancel_payment_adjustment, PaymentID, ID}, St) ->
_ = assert_invoice_accessible(St), _ = assert_invoice_accessible(St),
PaymentSession = get_payment_session(PaymentID, St), PaymentSession = get_payment_session(PaymentID, St),
Adjustment = hg_invoice_payment:get_adjustment(ID, PaymentSession),
PaymentOpts = get_payment_opts(Adjustment#domain_InvoicePaymentAdjustment.created_at, St),
wrap_payment_impact( wrap_payment_impact(
PaymentID, PaymentID,
hg_invoice_payment:cancel_adjustment(ID, PaymentSession, get_payment_opts(St)), hg_invoice_payment:cancel_adjustment(ID, PaymentSession, PaymentOpts),
St St
); );
@ -648,11 +661,6 @@ wrap_payment_impact(PaymentID, {Response, {Changes, Action}}, St) ->
state => St state => St
}. }.
checkout_party(St = #st{invoice = #domain_Invoice{created_at = CreationTimestamp}}) ->
PartyID = get_party_id(St),
% TODO repalce with checkout by revision
hg_party_machine:checkout(PartyID, {timestamp, CreationTimestamp}).
handle_result(#{state := St} = Params) -> handle_result(#{state := St} = Params) ->
_ = log_changes(maps:get(changes, Params, []), St), _ = log_changes(maps:get(changes, Params, []), St),
Result = handle_result_changes(Params, handle_result_action(Params, #{})), Result = handle_result_changes(Params, handle_result_action(Params, #{})),

View File

@ -48,7 +48,7 @@
-export([cancel/2]). -export([cancel/2]).
-export([refund/3]). -export([refund/3]).
-export([create_adjustment/3]). -export([create_adjustment/4]).
-export([capture_adjustment/3]). -export([capture_adjustment/3]).
-export([cancel_adjustment/3]). -export([cancel_adjustment/3]).
@ -863,10 +863,10 @@ get_refund_cashflow_plan(RefundSt) ->
%% %%
-spec create_adjustment(adjustment_params(), st(), opts()) -> -spec create_adjustment(hg_datetime:timestamp(), adjustment_params(), st(), opts()) ->
{adjustment(), result()}. {adjustment(), result()}.
create_adjustment(Params, St, Opts) -> create_adjustment(Timestamp, Params, St, Opts) ->
Payment = get_payment(St), Payment = get_payment(St),
Revision = get_adjustment_revision(Params), Revision = get_adjustment_revision(Params),
_ = assert_payment_status(captured, Payment), _ = assert_payment_status(captured, Payment),
@ -884,7 +884,7 @@ create_adjustment(Params, St, Opts) ->
Adjustment = #domain_InvoicePaymentAdjustment{ Adjustment = #domain_InvoicePaymentAdjustment{
id = ID, id = ID,
status = ?adjustment_pending(), status = ?adjustment_pending(),
created_at = hg_datetime:format_now(), created_at = Timestamp,
domain_revision = Revision, domain_revision = Revision,
reason = Params#payproc_InvoicePaymentAdjustmentParams.reason, reason = Params#payproc_InvoicePaymentAdjustmentParams.reason,
old_cash_flow_inverse = hg_cashflow:revert(get_cashflow(St)), old_cash_flow_inverse = hg_cashflow:revert(get_cashflow(St)),

View File

@ -15,6 +15,7 @@
-export([get_first_contract_id/1]). -export([get_first_contract_id/1]).
-export([get_first_battle_ready_contract_id/1]). -export([get_first_battle_ready_contract_id/1]).
-export([get_first_payout_tool_id/2]). -export([get_first_payout_tool_id/2]).
-export([adjust_contract/3]).
-export([make_battle_ready_contract_params/2]). -export([make_battle_ready_contract_params/2]).
-export([make_battle_ready_payout_tool_params/0]). -export([make_battle_ready_payout_tool_params/0]).
@ -291,14 +292,7 @@ create_battle_ready_shop(Category, Currency, TemplateRef, PaymentInstitutionRef,
?shop_modification(ShopID, {creation, ShopParams}), ?shop_modification(ShopID, {creation, ShopParams}),
?shop_modification(ShopID, {shop_account_creation, ShopAccountParams}) ?shop_modification(ShopID, {shop_account_creation, ShopAccountParams})
], ],
#payproc_Claim{id = ClaimID, revision = ClaimRevision, status = Status} = ok = ensure_claim_accepted(hg_client_party:create_claim(Changeset, Client), Client),
hg_client_party:create_claim(Changeset, Client),
case Status of
{accepted, _} ->
ok;
_ ->
ok = hg_client_party:accept_claim(ClaimID, ClaimRevision, Client)
end,
_Shop = hg_client_party:get_shop(ShopID, Client), _Shop = hg_client_party:get_shop(ShopID, Client),
ShopID. ShopID.
@ -335,6 +329,29 @@ get_first_battle_ready_contract_id(Client) ->
error(not_found) error(not_found)
end. end.
-spec adjust_contract(contract_id(), contract_tpl(), Client :: pid()) -> ok.
adjust_contract(ContractID, TemplateRef, Client) ->
ensure_claim_accepted(hg_client_party:create_claim([
{contract_modification, #payproc_ContractModificationUnit{
id = ContractID,
modification = {adjustment_modification, #payproc_ContractAdjustmentModificationUnit{
adjustment_id = hg_utils:unique_id(),
modification = {creation, #payproc_ContractAdjustmentParams{
template = TemplateRef
}}
}}
}}
], Client), Client).
ensure_claim_accepted(#payproc_Claim{id = ClaimID, revision = ClaimRevision, status = Status}, Client) ->
case Status of
{accepted, _} ->
ok;
_ ->
ok = hg_client_party:accept_claim(ClaimID, ClaimRevision, Client)
end.
-spec get_account(account_id()) -> account(). -spec get_account(account_id()) -> account().
get_account(AccountID) -> get_account(AccountID) ->

View File

@ -737,6 +737,7 @@ payment_adjustment_success(C) ->
PaymentID = await_payment_capture(InvoiceID, PaymentID, Client), PaymentID = await_payment_capture(InvoiceID, PaymentID, Client),
PrvAccount1 = get_cashflow_account({provider, settlement}, CF1), PrvAccount1 = get_cashflow_account({provider, settlement}, CF1),
SysAccount1 = get_cashflow_account({system, settlement}, CF1), SysAccount1 = get_cashflow_account({system, settlement}, CF1),
MrcAccount1 = get_cashflow_account({merchant, settlement}, CF1),
%% update terminal cashflow %% update terminal cashflow
ProviderRef = ?prv(100), ProviderRef = ?prv(100),
Provider = hg_domain:get(hg_domain:head(), {provider, ProviderRef}), Provider = hg_domain:get(hg_domain:head(), {provider, ProviderRef}),
@ -753,6 +754,10 @@ payment_adjustment_success(C) ->
} }
}} }}
), ),
%% update merchant fees
PartyClient = cfg(party_client, C),
Shop = hg_client_party:get_shop(cfg(shop_id, C), PartyClient),
ok = hg_ct_helper:adjust_contract(Shop#domain_Shop.contract_id, ?tmpl(3), PartyClient),
%% make an adjustment %% make an adjustment
Params = make_adjustment_params(Reason = <<"imdrunk">>), Params = make_adjustment_params(Reason = <<"imdrunk">>),
?adjustment(AdjustmentID, ?adjustment_pending()) = Adjustment = ?adjustment(AdjustmentID, ?adjustment_pending()) = Adjustment =
@ -778,8 +783,11 @@ payment_adjustment_success(C) ->
#domain_InvoicePaymentAdjustment{new_cash_flow = CF2} = Adjustment, #domain_InvoicePaymentAdjustment{new_cash_flow = CF2} = Adjustment,
PrvAccount2 = get_cashflow_account({provider, settlement}, CF2), PrvAccount2 = get_cashflow_account({provider, settlement}, CF2),
SysAccount2 = get_cashflow_account({system, settlement}, CF2), SysAccount2 = get_cashflow_account({system, settlement}, CF2),
500 = maps:get(own_amount, PrvAccount1) - maps:get(own_amount, PrvAccount2), MrcAccount2 = get_cashflow_account({merchant, settlement}, CF2),
-480 = maps:get(own_amount, SysAccount1) - maps:get(own_amount, SysAccount2). 500 = MrcDiff = maps:get(own_amount, MrcAccount2) - maps:get(own_amount, MrcAccount1),
-500 = PrvDiff = maps:get(own_amount, PrvAccount2) - maps:get(own_amount, PrvAccount1),
SysDiff = MrcDiff + PrvDiff - 20,
SysDiff = maps:get(own_amount, SysAccount2) - maps:get(own_amount, SysAccount1).
get_cashflow_account(Type, CF) -> get_cashflow_account(Type, CF) ->
[ID] = [V || #domain_FinalCashFlowPosting{ [ID] = [V || #domain_FinalCashFlowPosting{
@ -793,6 +801,27 @@ get_cashflow_account(Type, CF) ->
get_adjustment_fixture(Revision) -> get_adjustment_fixture(Revision) ->
PaymentInstitution = hg_domain:get(Revision, {payment_institution, ?pinst(1)}), PaymentInstitution = hg_domain:get(Revision, {payment_institution, ?pinst(1)}),
[ [
{term_set_hierarchy, #domain_TermSetHierarchyObject{
ref = ?trms(3),
data = #domain_TermSetHierarchy{
term_sets = [#domain_TimedTermSet{
action_time = #'TimestampInterval'{},
terms = #domain_TermSet{
payments = #domain_PaymentsServiceTerms{
fees = {value, [
?cfpost(
{merchant, settlement},
{system, settlement},
?share(40, 1000, operation_amount)
)
]}
}
}
}]
}
}},
{payment_institution, #domain_PaymentInstitutionObject{ {payment_institution, #domain_PaymentInstitutionObject{
ref = ?pinst(1), ref = ?pinst(1),
data = PaymentInstitution#domain_PaymentInstitution{ data = PaymentInstitution#domain_PaymentInstitution{
@ -853,6 +882,7 @@ get_adjustment_fixture(Revision) ->
risk_coverage = low risk_coverage = low
} }
}} }}
]. ].
get_adjustment_provider_cashflow(initial) -> get_adjustment_provider_cashflow(initial) ->
@ -1960,6 +1990,7 @@ construct_domain_fixture() ->
hg_ct_fixture:construct_contract_template(?tmpl(1), ?trms(1)), hg_ct_fixture:construct_contract_template(?tmpl(1), ?trms(1)),
hg_ct_fixture:construct_contract_template(?tmpl(2), ?trms(2)), hg_ct_fixture:construct_contract_template(?tmpl(2), ?trms(2)),
hg_ct_fixture:construct_contract_template(?tmpl(3), ?trms(3)),
hg_ct_fixture:construct_system_account_set(?sas(1)), hg_ct_fixture:construct_system_account_set(?sas(1)),
hg_ct_fixture:construct_system_account_set(?sas(2)), hg_ct_fixture:construct_system_account_set(?sas(2)),
@ -2100,6 +2131,13 @@ construct_domain_fixture() ->
}] }]
} }
}}, }},
{term_set_hierarchy, #domain_TermSetHierarchyObject{
ref = ?trms(3),
data = #domain_TermSetHierarchy{
parent_terms = ?trms(1),
term_sets = []
}
}},
{provider, #domain_ProviderObject{ {provider, #domain_ProviderObject{
ref = ?prv(1), ref = ?prv(1),