From e97c3de5520ec2dc79cb2aab410a2c27946b36ab Mon Sep 17 00:00:00 2001 From: dominicsanto Date: Wed, 10 May 2023 13:22:42 +0200 Subject: [PATCH 1/2] wip: Transfer functionality :hourglass: --- investec_open_api-1.1.0.gem | Bin 10752 -> 0 bytes lib/investec_open_api/client.rb | 20 +++++++++ lib/investec_open_api/models/transfer.rb | 38 +++++++++++++++++ spec/lib/investec_open_api/client_spec.rb | 48 ++++++++++++++++++++++ 4 files changed, 106 insertions(+) delete mode 100644 investec_open_api-1.1.0.gem create mode 100644 lib/investec_open_api/models/transfer.rb diff --git a/investec_open_api-1.1.0.gem b/investec_open_api-1.1.0.gem deleted file mode 100644 index 1ae14c78bc01a808623bbdccce1dd4fdbdc69f11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10752 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 RXa9}B-w6DT!2cfz{0C+vHO2q{ diff --git a/lib/investec_open_api/client.rb b/lib/investec_open_api/client.rb index df588ed..0e4cd8d 100644 --- a/lib/investec_open_api/client.rb +++ b/lib/investec_open_api/client.rb @@ -24,6 +24,26 @@ def transactions(account_id) end end + def transfer(account_id, to_account_id, amount, my_reference, their_reference) + response = connection.post( + "za/pb/v1/accounts/#{account_id}/transfermultiple", + { + transferList: [ + { + beneficiaryAccountId: to_account_id, + amount: amount, + myReference: my_reference, + theirReference: their_reference + } + ] + } + ) + + response.body["data"]["TransferResponses"].map do |transfer_raw| + InvestecOpenApi::Models::Transfer.from_api(transfer_raw) + end + end + private def get_oauth_token diff --git a/lib/investec_open_api/models/transfer.rb b/lib/investec_open_api/models/transfer.rb new file mode 100644 index 0000000..12f7c42 --- /dev/null +++ b/lib/investec_open_api/models/transfer.rb @@ -0,0 +1,38 @@ +module InvestecOpenApi::Models + class Transfer < Base + attribute :payment_reference_number + attribute :payment_date + attribute :status + attribute :beneficiary_name + attribute :beneficiary_account_id + attribute :authorisation_required + + def self.from_api(params = {}) + if params['PaymentReferenceNumber'].present? + params['payment_reference_number'] = params['PaymentReferenceNumber'] + end + + if params['PaymentDate'].present? + params['payment_date'] = params['PaymentDate'] + end + + if params['Status'].present? + params['status'] = params['Status'] + end + + if params['BeneficiaryName'].present? + params['beneficiary_name'] = params['BeneficiaryName'] + end + + if params['BeneficiaryAccountId'].present? + params['beneficiary_account_id'] = params['BeneficiaryAccountId'] + end + + if params['AuthorisationRequired'].present? + params['authorisation_required'] = params['AuthorisationRequired'] + end + + super + end + end +end diff --git a/spec/lib/investec_open_api/client_spec.rb b/spec/lib/investec_open_api/client_spec.rb index dcfe629..fceaf4b 100644 --- a/spec/lib/investec_open_api/client_spec.rb +++ b/spec/lib/investec_open_api/client_spec.rb @@ -140,4 +140,52 @@ expect(transactions.first).to be_an_instance_of(InvestecOpenApi::Models::Transaction) end end + + describe "#transfer" do + before do + stub_request(:get, "#{api_url}za/pb/v1/accounts/12345/transfermultiple") + .with( + body: { + transferList: [ + { + beneficiaryAccountId: '6789', + amount: 10, + myReference: 'Library Transfer', + theirReference: 'Library Transfer' + } + ] + }, + headers: { + "Accept" => "application/json", + "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3", + "Authorization" => "Bearer 123", + "User-Agent" => "Faraday v1.10.3" + } + ) + .to_return( + body: { + data: { + "TransferResponses": [ + { + "PaymentReferenceNumber": "UBP0111111111", + "PaymentDate": "10/05/2023", + "Status": "- No authorisation necessary
- Payment/Transfer effective date 10/05/2023", + "BeneficiaryName": "API transfer", + "BeneficiaryAccountId": "6789", + "AuthorisationRequired": false + } + ] + } + }.to_json + ) + + client.authenticate! + end + + it "returns transfer details based on the transfer as InvestecOpenApi::Models::Transfer instances" do + transferResponses = client.transfer('12345', '6789', 10, 'API Transfer', 'API Transfer') + + expect(transferResponses.first).to be_an_instance_of(InvestecOpenApi::Models::Transaction) + end + end end From 5e1f45aa4853ed97949f0e9860e77c22d6d7baa5 Mon Sep 17 00:00:00 2001 From: dominicsanto Date: Wed, 10 May 2023 13:40:54 +0200 Subject: [PATCH 2/2] add: specs for transfer functionality --- lib/investec_open_api/client.rb | 1 + spec/lib/investec_open_api/client_spec.rb | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/investec_open_api/client.rb b/lib/investec_open_api/client.rb index 0e4cd8d..39dbf00 100644 --- a/lib/investec_open_api/client.rb +++ b/lib/investec_open_api/client.rb @@ -2,6 +2,7 @@ require "faraday_middleware" require "investec_open_api/models/account" require "investec_open_api/models/transaction" +require "investec_open_api/models/transfer" class InvestecOpenApi::Client INVESTEC_API_URL="https://openapi.investec.com/" diff --git a/spec/lib/investec_open_api/client_spec.rb b/spec/lib/investec_open_api/client_spec.rb index fceaf4b..a4f63fa 100644 --- a/spec/lib/investec_open_api/client_spec.rb +++ b/spec/lib/investec_open_api/client_spec.rb @@ -143,7 +143,7 @@ describe "#transfer" do before do - stub_request(:get, "#{api_url}za/pb/v1/accounts/12345/transfermultiple") + stub_request(:post, "#{api_url}za/pb/v1/accounts/12345/transfermultiple") .with( body: { transferList: [ @@ -183,9 +183,9 @@ end it "returns transfer details based on the transfer as InvestecOpenApi::Models::Transfer instances" do - transferResponses = client.transfer('12345', '6789', 10, 'API Transfer', 'API Transfer') + transferResponses = client.transfer('12345', '6789', 10, 'Library Transfer', 'Library Transfer') - expect(transferResponses.first).to be_an_instance_of(InvestecOpenApi::Models::Transaction) + expect(transferResponses.first).to be_an_instance_of(InvestecOpenApi::Models::Transfer) end end end