diff --git a/apps/hellgate/src/hg_invoice_payment_chargeback.erl b/apps/hellgate/src/hg_invoice_payment_chargeback.erl index 7523cc9..629688f 100644 --- a/apps/hellgate/src/hg_invoice_payment_chargeback.erl +++ b/apps/hellgate/src/hg_invoice_payment_chargeback.erl @@ -280,10 +280,13 @@ do_create(Opts, CreateParams = ?chargeback_params(Levy, Body, _Reason)) -> CreatedAt = hg_datetime:format_now(), Invoice = get_opts_invoice(Opts), Party = get_opts_party(Opts), + Route = get_opts_route(Opts), Payment = get_opts_payment(Opts), ShopID = get_invoice_shop_id(Invoice), Shop = hg_party:get_shop(ShopID, Party), VS = collect_validation_varset(Party, Shop, Payment, Body), + PaymentsTerms = hg_routing:get_payment_terms(Route, VS, Revision), + ProviderTerms = get_provider_chargeback_terms(PaymentsTerms, Payment), ServiceTerms = get_merchant_chargeback_terms(Party, Shop, VS, Revision, CreatedAt), _ = validate_currency(Body, Payment), _ = validate_currency(Levy, Payment), @@ -291,6 +294,7 @@ do_create(Opts, CreateParams = ?chargeback_params(Levy, Body, _Reason)) -> _ = validate_contract_active(get_contract(Party, Shop)), _ = validate_service_terms(ServiceTerms), _ = validate_eligibility_time(ServiceTerms), + _ = validate_provider_terms(ProviderTerms), Chargeback = build_chargeback(Opts, CreateParams, Revision, CreatedAt), Action = hg_machine_action:instant(), Result = {[?chargeback_created(Chargeback)], Action}, @@ -558,6 +562,10 @@ validate_service_terms(#domain_PaymentChargebackServiceTerms{allow = {constant, validate_service_terms(undefined) -> throw(#payproc_OperationNotPermitted{}). +validate_provider_terms(ProviderTerms) -> + _ = get_chargeback_provider_cash_flow(ProviderTerms), + ok. + validate_contract_active(#domain_Contract{status = {active, _}}) -> ok; validate_contract_active(#domain_Contract{status = Status}) -> diff --git a/apps/hellgate/test/hg_invoice_tests_SUITE.erl b/apps/hellgate/test/hg_invoice_tests_SUITE.erl index 9280676..362175a 100644 --- a/apps/hellgate/test/hg_invoice_tests_SUITE.erl +++ b/apps/hellgate/test/hg_invoice_tests_SUITE.erl @@ -103,6 +103,7 @@ -export([payment_hold_auto_capturing/1]). -export([create_chargeback_not_allowed/1]). +-export([create_chargeback_provision_terms_not_allowed/1]). -export([create_chargeback_inconsistent/1]). -export([create_chargeback_exceeded/1]). -export([create_chargeback_idempotency/1]). @@ -352,6 +353,7 @@ groups() -> {chargebacks, [], [ create_chargeback_not_allowed, + create_chargeback_provision_terms_not_allowed, create_chargeback_inconsistent, create_chargeback_exceeded, create_chargeback_idempotency, @@ -692,6 +694,8 @@ init_per_testcase(Name = limit_hold_payment_tool_not_supported, C) -> override_domain_fixture(fun patch_with_unsupported_payment_tool/2, Name, C); init_per_testcase(Name = limit_hold_two_routes_failure, C) -> override_domain_fixture(fun patch_providers_limits_to_fail_and_overflow/2, Name, C); +init_per_testcase(Name = create_chargeback_provision_terms_not_allowed, C) -> + override_domain_fixture(fun unset_providers_chargebacks_terms/2, Name, C); init_per_testcase(Name = repair_fail_routing_succeeded, C) -> meck:expect( hg_limiter, @@ -1687,6 +1691,25 @@ patch_providers_limits_to_fail_and_overflow(Revision, _C) -> ]) ]. +unset_providers_chargebacks_terms(Revision, _C) -> + lists:flatten([unset_provider_chargebacks_terms(Revision, ProviderRef) || ProviderRef <- [?prv(2)]]). + +unset_provider_chargebacks_terms(Revision, ProviderRef) -> + Provider = + #domain_Provider{terms = Terms} = + hg_domain:get(Revision, {provider, ProviderRef}), + PaymentsTermSet = Terms#domain_ProvisionTermSet.payments, + [ + {provider, #domain_ProviderObject{ + ref = ProviderRef, + data = Provider#domain_Provider{ + terms = Terms#domain_ProvisionTermSet{ + payments = PaymentsTermSet#domain_PaymentsProvisionTerms{chargebacks = undefined} + } + } + }} + ]. + change_terms_limit_config_version(Revision, LimitConfigRevision) -> change_terms_limit_config_version(Revision, ?prv(5), [ #domain_TurnoverLimit{ @@ -3059,6 +3082,26 @@ create_chargeback_not_allowed(C) -> Result = hg_client_invoicing:create_chargeback(InvoiceID, PaymentID, CBParams, Client), ?assertMatch({exception, #payproc_OperationNotPermitted{}}, Result). +-spec create_chargeback_provision_terms_not_allowed(config()) -> _ | no_return(). +create_chargeback_provision_terms_not_allowed(C) -> + %% NOTE See fixture setup in `unset_providers_chargebacks_terms' + Cost = 42000, + Client = cfg(client, C), + PartyClient = cfg(party_client, C), + ShopID = hg_ct_helper:create_battle_ready_shop( + cfg(party_id, C), + ?cat(2), + <<"RUB">>, + ?tmpl(2), + ?pinst(2), + PartyClient + ), + InvoiceID = start_invoice(ShopID, <<"rubberduck">>, make_due_date(10), Cost, C), + PaymentID = execute_payment(InvoiceID, make_payment_params(?pmt_sys(<<"visa-ref">>)), Client), + CBParams = make_chargeback_params(?cash(1000, <<"RUB">>)), + Result = hg_client_invoicing:create_chargeback(InvoiceID, PaymentID, CBParams, Client), + ?assertMatch({exception, #payproc_OperationNotPermitted{}}, Result). + -spec create_chargeback_inconsistent(config()) -> _ | no_return(). create_chargeback_inconsistent(C) -> Cost = 42000, diff --git a/rebar.lock b/rebar.lock index b556b42..47d9f3e 100644 --- a/rebar.lock +++ b/rebar.lock @@ -58,7 +58,7 @@ {git,"https://github.com/valitydev/machinegun-proto.git", {ref,"96f7f11b184c29d8b7e83cd7646f3f2c13662bda"}}, 0}, - {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},2}, + {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.3.0">>},2}, {<<"msgpack_proto">>, {git,"https://github.com/valitydev/msgpack-proto.git", {ref,"7e447496aa5df4a5f1ace7ef2e3c31248b2a3ed0"}}, @@ -104,7 +104,7 @@ {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},2}, {<<"woody">>, {git,"https://github.com/valitydev/woody_erlang.git", - {ref,"3e2337a818086f33f0a1ede5d204aee7744c7c36"}}, + {ref,"81219ba5408e1c67f5eaed3c7e566ede42da88d4"}}, 0}]}. [ {pkg_hash,[ @@ -123,7 +123,7 @@ {<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>}, {<<"jsx">>, <<"D12516BAA0BB23A59BB35DCCAF02A1BD08243FCBB9EFE24F2D9D056CCFF71268">>}, {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, - {<<"mimerl">>, <<"67E2D3F571088D5CFD3E550C383094B47159F3EEE8FFA08E64106CDF5E981BE3">>}, + {<<"mimerl">>, <<"D0CD9FC04B9061F82490F6581E0128379830E78535E017F7780F37FEA7545726">>}, {<<"opentelemetry">>, <<"988AC3C26ACAC9720A1D4FB8D9DC52E95B45ECFEC2D5B5583276A09E8936BC5E">>}, {<<"opentelemetry_api">>, <<"7B69ED4F40025C005DE0B74FCE8C0549625D59CB4DF12D15C32FE6DC5076FF42">>}, {<<"opentelemetry_exporter">>, <<"1D8809C0D4F4ACF986405F7700ED11992BCBDB6A4915DD11921E80777FFA7167">>}, @@ -153,7 +153,7 @@ {<<"idna">>, <<"92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA">>}, {<<"jsx">>, <<"0C5CC8FDC11B53CC25CF65AC6705AD39E54ECC56D1C22E4ADB8F5A53FB9427F3">>}, {<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>}, - {<<"mimerl">>, <<"F278585650AA581986264638EBF698F8BB19DF297F66AD91B18910DFC6E19323">>}, + {<<"mimerl">>, <<"A1E15A50D1887217DE95F0B9B0793E32853F7C258A5CD227650889B38839FE9D">>}, {<<"opentelemetry">>, <<"8E09EDC26AAD11161509D7ECAD854A3285D88580F93B63B0B1CF0BAC332BFCC0">>}, {<<"opentelemetry_api">>, <<"6D7A27B7CAD2AD69A09CABF6670514CAFCEC717C8441BEB5C96322BAC3D05350">>}, {<<"opentelemetry_exporter">>, <<"2B40007F509D38361744882FD060A8841AF772AB83BB542AA5350908B303AD65">>},