diff --git a/apps/hellgate/src/hg_claim.erl b/apps/hellgate/src/hg_claim.erl index 65fe5cd..b1489b9 100644 --- a/apps/hellgate/src/hg_claim.erl +++ b/apps/hellgate/src/hg_claim.erl @@ -1,6 +1,7 @@ -module(hg_claim). -include("party_events.hrl"). +-include_lib("dmsl/include/dmsl_domain_thrift.hrl"). -include_lib("dmsl/include/dmsl_payment_processing_thrift.hrl"). -export([create/5]). @@ -439,7 +440,7 @@ assert_changeset_applicable([Change | Others], Timestamp, Revision, Party) -> ok = assert_contract_change_applicable(ID, Modification, Contract); ?shop_modification(ID, Modification) -> Shop = hg_party:get_shop(ID, Party), - ok = assert_shop_change_applicable(ID, Modification, Shop, Party); + ok = assert_shop_change_applicable(ID, Modification, Shop, Party, Revision); ?contractor_modification(ID, Modification) -> Contractor = hg_party:get_contractor(ID, Party), ok = assert_contractor_change_applicable(ID, Modification, Contractor); @@ -482,27 +483,35 @@ assert_contract_change_applicable(ID, ?payout_tool_creation(PayoutToolID, _), Co assert_contract_change_applicable(_, _, _) -> ok. -assert_shop_change_applicable(_, {creation, _}, undefined, _) -> +assert_shop_change_applicable(_, {creation, _}, undefined, _, _) -> ok; -assert_shop_change_applicable(ID, _AnyModification, undefined, _) -> +assert_shop_change_applicable(ID, _AnyModification, undefined, _, _) -> raise_invalid_changeset(?invalid_shop(ID, {not_exists, ID})); -assert_shop_change_applicable(ID, {creation, _}, #domain_Shop{}, _) -> +assert_shop_change_applicable(ID, {creation, _}, #domain_Shop{}, _, _) -> raise_invalid_changeset(?invalid_shop(ID, {already_exists, ID})); assert_shop_change_applicable( _ID, {shop_account_creation, _}, #domain_Shop{account = Account}, - _Party + _Party, + _Revision ) when Account /= undefined -> throw(#'InvalidRequest'{errors = [<<"Can't change shop's account">>]}); assert_shop_change_applicable( _ID, {contract_modification, #payproc_ShopContractModification{contract_id = NewContractID}}, #domain_Shop{contract_id = OldContractID}, - Party + Party, + Revision ) -> - assert_payment_institutions_equals(OldContractID, NewContractID, Party); -assert_shop_change_applicable(_, _, _, _) -> + OldContract = hg_party:get_contract(OldContractID, Party), + case hg_party:get_contract(NewContractID, Party) of + #domain_Contract{} = NewContract -> + assert_payment_institution_realm_equals(OldContract, NewContract, Revision); + undefined -> + raise_invalid_changeset(?invalid_contract(NewContractID, {not_exists, NewContractID})) + end; +assert_shop_change_applicable(_, _, _, _, _) -> ok. assert_contractor_change_applicable(_, {creation, _}, undefined) -> @@ -529,21 +538,25 @@ assert_wallet_change_applicable( assert_wallet_change_applicable(_, _, _) -> ok. -assert_payment_institutions_equals(OldContractID, NewContractID, Party) -> - #domain_Contract{payment_institution = OldRef} = hg_party:get_contract(OldContractID, Party), - case hg_party:get_contract(NewContractID, Party) of - #domain_Contract{payment_institution = OldRef} -> +assert_payment_institution_realm_equals( + #domain_Contract{id = OldContractID, payment_institution = OldRef}, + #domain_Contract{id = NewContractID, payment_institution = NewRef}, + Revision +) -> + OldRealm = get_payment_institution_realm(OldRef, Revision, OldContractID), + case get_payment_institution_realm(NewRef, Revision, NewContractID) of + OldRealm -> ok; - #domain_Contract{payment_institution = NewRef} -> - % Can't change shop's payment institution - raise_invalid_changeset(?invalid_contract( - NewContractID, - {invalid_object_reference, #payproc_InvalidObjectReference{ - ref = make_optional_domain_ref(payment_institution, NewRef) - }} - )); - undefined -> - raise_invalid_changeset(?invalid_contract(NewContractID, {not_exists, NewContractID})) + _NewRealm -> + raise_invalid_payment_institution(NewContractID, NewRef) + end. + +get_payment_institution_realm(Ref, Revision, ContractID) -> + case hg_domain:find(Revision, {payment_institution, Ref}) of + #domain_PaymentInstitution{} = P -> + hg_payment_institution:get_realm(P); + notfound -> + raise_invalid_payment_institution(ContractID, Ref) end. assert_changeset_acceptable(Changeset, Timestamp, Revision, Party0) -> @@ -551,6 +564,20 @@ assert_changeset_acceptable(Changeset, Timestamp, Revision, Party0) -> Party = apply_effects(Effects, Timestamp, Party0), hg_party:assert_party_objects_valid(Timestamp, Revision, Party). +-spec raise_invalid_payment_institution( + dmsl_domain_thrift:'ContractID'(), + dmsl_domain_thrift:'PaymentInstitutionRef'() | undefined +) -> + no_return(). + +raise_invalid_payment_institution(ContractID, Ref) -> + raise_invalid_changeset(?invalid_contract( + ContractID, + {invalid_object_reference, #payproc_InvalidObjectReference{ + ref = make_optional_domain_ref(payment_institution, Ref) + }} + )). + make_optional_domain_ref(_, undefined) -> undefined; make_optional_domain_ref(Type, Ref) -> diff --git a/apps/hellgate/src/hg_payment_institution.erl b/apps/hellgate/src/hg_payment_institution.erl index cd70733..f63ef18 100644 --- a/apps/hellgate/src/hg_payment_institution.erl +++ b/apps/hellgate/src/hg_payment_institution.erl @@ -5,6 +5,7 @@ %% -export([get_system_account/4]). +-export([get_realm/1]). -export([is_live/1]). %% @@ -12,6 +13,7 @@ -type varset() :: hg_selector:varset(). -type revision() :: hg_domain:revision(). -type payment_inst() :: dmsl_domain_thrift:'PaymentInstitution'(). +-type realm() :: dmsl_domain_thrift:'PaymentInstitutionRealm'(). %% @@ -28,6 +30,11 @@ get_system_account(Currency, VS, Revision, #domain_PaymentInstitution{system_acc error({misconfiguration, {'No system account for a given currency', Currency}}) end. +-spec get_realm(payment_inst()) -> realm(). + +get_realm(#domain_PaymentInstitution{realm = Realm}) -> + Realm. + -spec is_live(payment_inst()) -> boolean(). is_live(#domain_PaymentInstitution{realm = Realm}) -> diff --git a/apps/hellgate/test/hg_party_tests_SUITE.erl b/apps/hellgate/test/hg_party_tests_SUITE.erl index 293b6fa..bceeb1b 100644 --- a/apps/hellgate/test/hg_party_tests_SUITE.erl +++ b/apps/hellgate/test/hg_party_tests_SUITE.erl @@ -111,7 +111,6 @@ all() -> {group, shop_management}, {group, shop_account_lazy_creation}, {group, contractor_management}, - {group, wallet_management}, {group, claim_management}, @@ -799,7 +798,24 @@ shop_update(C) -> Changeset2 = [?shop_modification(ShopID, {location_modification, Location})], Claim2 = assert_claim_pending(hg_client_party:create_claim(Changeset2, Client), Client), ok = accept_claim(Claim2, Client), - #domain_Shop{location = Location, details = Details} = hg_client_party:get_shop(ShopID, Client). + #domain_Shop{location = Location, details = Details} = hg_client_party:get_shop(ShopID, Client), + + PayoutToolParams = hg_ct_helper:make_battle_ready_payout_tool_params(), + ContractID = <<"CONTRACT_IN_DIFFERENT_PAYMENT_INST">>, + PayoutToolID = <<"1">>, + Changeset3 = [ + ?contract_modification(ContractID, {creation, make_contract_params(?tmpl(2), ?pinst(3))}), + ?contract_modification(ContractID, ?payout_tool_creation(PayoutToolID, PayoutToolParams)), + ?shop_modification(ShopID, ?shop_contract_modification(ContractID, PayoutToolID)) + ], + Claim3 = assert_claim_pending(hg_client_party:create_claim(Changeset3, Client), Client), + ok = accept_claim(Claim3, Client), + #domain_Shop{ + location = Location, + details = Details, + contract_id = ContractID, + payout_tool_id = PayoutToolID + } = hg_client_party:get_shop(ShopID, Client). shop_update_before_confirm(C) -> Client = cfg(client, C), @@ -1318,7 +1334,10 @@ make_contract_params() -> make_contract_params(undefined). make_contract_params(TemplateRef) -> - hg_ct_helper:make_battle_ready_contract_params(TemplateRef, ?pinst(2)). + make_contract_params(TemplateRef, ?pinst(2)). + +make_contract_params(TemplateRef, PaymentInstitutionRef) -> + hg_ct_helper:make_battle_ready_contract_params(TemplateRef, PaymentInstitutionRef). make_contract_w_contractor_params(ContractorID) -> #payproc_ContractParams{ @@ -1494,6 +1513,19 @@ construct_domain_fixture() -> } }}, + {payment_institution, #domain_PaymentInstitutionObject{ + ref = ?pinst(3), + data = #domain_PaymentInstitution{ + name = <<"Chetky Payments Inc.">>, + system_account_set = {value, ?sas(2)}, + default_contract_template = {value, ?tmpl(2)}, + providers = {value, ?ordset([])}, + inspector = {value, ?insp(1)}, + residences = [], + realm = live + } + }}, + {globals, #domain_GlobalsObject{ ref = #domain_GlobalsRef{}, data = #domain_Globals{