belvo 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +18 -0
- data/.github/pull_request_template.md +10 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +27 -0
- data/.travis.yml +9 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +103 -0
- data/LICENSE +21 -0
- data/README.md +67 -0
- data/Rakefile +8 -0
- data/belvo.gemspec +42 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/belvo.rb +84 -0
- data/lib/belvo/exceptions.rb +31 -0
- data/lib/belvo/http.rb +165 -0
- data/lib/belvo/options.rb +114 -0
- data/lib/belvo/resources.rb +343 -0
- data/lib/belvo/version.rb +6 -0
- metadata +196 -0
data/bin/setup
ADDED
data/lib/belvo.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'belvo/http'
|
4
|
+
require 'belvo/exceptions'
|
5
|
+
require 'belvo/resources'
|
6
|
+
|
7
|
+
module Belvo
|
8
|
+
# Allows easy access to Belvo API servers.
|
9
|
+
class Client
|
10
|
+
# Current Belvo API session
|
11
|
+
# @return [APISession]
|
12
|
+
attr_reader :session
|
13
|
+
|
14
|
+
# @param secret_key_id [String]
|
15
|
+
# @param secret_key_password [String]
|
16
|
+
# @param url [String, nil] API host URL, can be set from the environment
|
17
|
+
# using the variable name BELVO_API_URL
|
18
|
+
# @return [APISession] Authenticated Belvo API session
|
19
|
+
def initialize(secret_key_id, secret_key_password, url = nil)
|
20
|
+
(belvo_api_url = url) || ENV['BELVO_API_URL']
|
21
|
+
raise BelvoAPIError, 'You need to provide a URL.' if belvo_api_url.nil?
|
22
|
+
|
23
|
+
@session = Belvo::APISession.new(belvo_api_url)
|
24
|
+
|
25
|
+
return if @session.login(secret_key_id, secret_key_password)
|
26
|
+
|
27
|
+
raise BelvoAPIError, 'Login failed.'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Provides access to Links resource
|
31
|
+
# @return [Link]
|
32
|
+
def links
|
33
|
+
@links = Link.new @session
|
34
|
+
end
|
35
|
+
|
36
|
+
# Provides access to Accounts resource
|
37
|
+
# @return [Account]
|
38
|
+
def accounts
|
39
|
+
@accounts = Account.new @session
|
40
|
+
end
|
41
|
+
|
42
|
+
# Provides access to Transactions resource
|
43
|
+
# @return [Transaction]
|
44
|
+
def transactions
|
45
|
+
@transactions = Transaction.new @session
|
46
|
+
end
|
47
|
+
|
48
|
+
# Provides access to Owners resource
|
49
|
+
# @return [Owner]
|
50
|
+
def owners
|
51
|
+
@owners = Owner.new @session
|
52
|
+
end
|
53
|
+
|
54
|
+
# Provides access to Balances resource
|
55
|
+
# @return [Balance]
|
56
|
+
def balances
|
57
|
+
@balances = Balance.new @session
|
58
|
+
end
|
59
|
+
|
60
|
+
# Provides access to Statements resource
|
61
|
+
# @return [Statement]
|
62
|
+
def statements
|
63
|
+
@statements = Statement.new @session
|
64
|
+
end
|
65
|
+
|
66
|
+
# Provides access to Invoices resource
|
67
|
+
# @return [Invoice]
|
68
|
+
def invoices
|
69
|
+
@invoices = Invoice.new @session
|
70
|
+
end
|
71
|
+
|
72
|
+
# Provides access to TaxReturns resource
|
73
|
+
# @return [TaxReturn]
|
74
|
+
def tax_returns
|
75
|
+
@tax_returns = TaxReturn.new @session
|
76
|
+
end
|
77
|
+
|
78
|
+
# Provides access to Instituions resource
|
79
|
+
# @return [Institution]
|
80
|
+
def institutions
|
81
|
+
@institutions = Institution.new @session
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Belvo
|
4
|
+
# Belvo API base error
|
5
|
+
class BelvoAPIError < StandardError
|
6
|
+
# @param message [String] Error short description
|
7
|
+
def initialize(message)
|
8
|
+
super(message)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Generic request error, any response with status different than 2xx.
|
13
|
+
class RequestError < BelvoAPIError
|
14
|
+
# HTTP code returned by Belvo API
|
15
|
+
# @return [Integer]
|
16
|
+
attr_reader :status_code
|
17
|
+
|
18
|
+
# Error message returned by Belvo API
|
19
|
+
# @return [JSON]
|
20
|
+
attr_reader :detail
|
21
|
+
|
22
|
+
# @param message [String] Error short description
|
23
|
+
# @param status_code [Integer] HTTP code
|
24
|
+
# @param detail [JSON] Detailed error(s) description
|
25
|
+
def initialize(message, status_code, detail)
|
26
|
+
super(message)
|
27
|
+
@status_code = status_code
|
28
|
+
@detail = detail
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/belvo/http.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
require 'typhoeus'
|
6
|
+
require 'typhoeus/adapters/faraday'
|
7
|
+
|
8
|
+
require 'belvo/version'
|
9
|
+
require 'belvo/exceptions'
|
10
|
+
|
11
|
+
module Belvo
|
12
|
+
# Describes a Belvo API session
|
13
|
+
class APISession
|
14
|
+
# @param url [String] Belvo API host url
|
15
|
+
# @return [Faraday::Connection]
|
16
|
+
def initialize(url)
|
17
|
+
@url = format('%<url>s/api/', url: url)
|
18
|
+
@session = Faraday::Connection.new(url: @url) do |faraday|
|
19
|
+
faraday.adapter :typhoeus
|
20
|
+
faraday.response :json
|
21
|
+
faraday.headers = {
|
22
|
+
'Content-Type' => 'application/json',
|
23
|
+
'User-Agent' => format(
|
24
|
+
'belvo-ruby (%<version>s)',
|
25
|
+
version: Belvo::VERSION
|
26
|
+
)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# Raise an error if the response code is not 2XX.
|
34
|
+
# @param response [Faraday::Response]
|
35
|
+
# @return [Faraday::Response]
|
36
|
+
def raise_for_status(response)
|
37
|
+
unless response.success?
|
38
|
+
raise RequestError.new(
|
39
|
+
'Request error',
|
40
|
+
response.status,
|
41
|
+
response.body.to_s
|
42
|
+
)
|
43
|
+
end
|
44
|
+
response
|
45
|
+
end
|
46
|
+
|
47
|
+
# Set and validate authentication credentials
|
48
|
+
# @return [Boolean] True if credentials are valid to authenticate
|
49
|
+
# to Belvo API else False.
|
50
|
+
def authenticate
|
51
|
+
@session.basic_auth(@key_id, @key_password)
|
52
|
+
response = @session.get('')
|
53
|
+
response.success?
|
54
|
+
end
|
55
|
+
|
56
|
+
# Perform GET request to a Belvo API endpoint. Needed for Detail and List.
|
57
|
+
# @param path [String] API Endpoint
|
58
|
+
# @param params [Hash] Params to be send as querystring
|
59
|
+
# @return [Faraday::Response]
|
60
|
+
# @raise [RequestError] If response code is different than 2XX
|
61
|
+
def get(path, params: nil)
|
62
|
+
params = {} if params.nil?
|
63
|
+
response = @session.get(path) do |req|
|
64
|
+
req.params = params
|
65
|
+
end
|
66
|
+
raise_for_status response
|
67
|
+
end
|
68
|
+
|
69
|
+
public
|
70
|
+
|
71
|
+
# Authenticate to Belvo API using the given credentials.
|
72
|
+
# @param secret_key_id [String]
|
73
|
+
# @param secret_key_password [String]
|
74
|
+
# @return [Boolean] True if credentials are valid to authenticate
|
75
|
+
# to Belvo API else False.
|
76
|
+
def login(secret_key_id, secret_key_password)
|
77
|
+
@key_id = secret_key_id
|
78
|
+
@key_password = secret_key_password
|
79
|
+
|
80
|
+
authenticate
|
81
|
+
end
|
82
|
+
|
83
|
+
# List results from an API endpoint. It will yield all results following
|
84
|
+
# pagination's next page, if any.
|
85
|
+
# @param path [String] API endpoint
|
86
|
+
# @param params [Hash] Params to be send as querystring
|
87
|
+
# @yield [Hash] Each result
|
88
|
+
# @raise [RequestError] If response code is different than 2XX
|
89
|
+
def list(path, params: nil)
|
90
|
+
params = {} if params.nil?
|
91
|
+
loop do
|
92
|
+
response = get(path, params: params)
|
93
|
+
response.body['results'].each do |item|
|
94
|
+
yield item if block_given?
|
95
|
+
end
|
96
|
+
|
97
|
+
break unless response.body['next']
|
98
|
+
|
99
|
+
path = response.body['next']
|
100
|
+
params = nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Show specific resource details
|
105
|
+
# @param path [String] API endpoint
|
106
|
+
# @param id [String] Resource UUID
|
107
|
+
# @param params [Hash] Params to be send as querystring
|
108
|
+
# @return [Hash] Resource details
|
109
|
+
# @raise [RequestError] If response code is different than 2XX
|
110
|
+
def detail(path, id, params: nil)
|
111
|
+
params = {} if params.nil?
|
112
|
+
|
113
|
+
resource_path = format('%<path>s%<id>s/', path: path, id: id)
|
114
|
+
response = get(resource_path, params)
|
115
|
+
|
116
|
+
raise_for_status response
|
117
|
+
response.body
|
118
|
+
end
|
119
|
+
|
120
|
+
# Perform a POST request to an API endpoint
|
121
|
+
# @param path [String] API endpoint
|
122
|
+
# @param data [object] JSON parseable object
|
123
|
+
# @return [Hash] Response details
|
124
|
+
# @raise [RequestError] If response code is different than 2XX
|
125
|
+
def post(path, data)
|
126
|
+
response = @session.post(path, data.to_json)
|
127
|
+
raise_for_status response
|
128
|
+
response.body
|
129
|
+
end
|
130
|
+
|
131
|
+
# Perform a PUT request to an specific resource
|
132
|
+
# @param path [String] API endpoint
|
133
|
+
# @param id [String] Resource UUID
|
134
|
+
# @param data [object] JSON parseable object
|
135
|
+
# @return [Hash] Response details
|
136
|
+
# @raise [RequestError] If response code is different than 2XX
|
137
|
+
def put(path, id, data)
|
138
|
+
url = format('%<path>s%<id>s/', path: path, id: id)
|
139
|
+
response = @session.put(url, data.to_json)
|
140
|
+
raise_for_status response
|
141
|
+
response.body
|
142
|
+
end
|
143
|
+
|
144
|
+
# Perform a PATCH request to an API endpoint
|
145
|
+
# @param path [String] API endpoint
|
146
|
+
# @param data [object] JSON parseable object
|
147
|
+
# @return [Hash] Response details
|
148
|
+
# @raise [RequestError] If response code is different than 2XX
|
149
|
+
def patch(path, data)
|
150
|
+
response = @session.patch(path, data.to_json)
|
151
|
+
raise_for_status response
|
152
|
+
response.body
|
153
|
+
end
|
154
|
+
|
155
|
+
# Delete existing resource
|
156
|
+
# @param path [String] API endpoint
|
157
|
+
# @param id [String] Resource UUID
|
158
|
+
# @return [Boolean] true if resource is successfully deleted else false
|
159
|
+
def delete(path, id)
|
160
|
+
resource_path = format('%<path>s%<id>s/', path: path, id: id)
|
161
|
+
response = @session.delete(resource_path)
|
162
|
+
response.success?
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday/options'
|
4
|
+
|
5
|
+
module Belvo
|
6
|
+
# @!class LinkOptions < Faraday::Options
|
7
|
+
# Contains the configurable properties for a Link
|
8
|
+
# @!attribute access_mode [rw] Link access mode (SINGLE or RECURRENT)
|
9
|
+
# @!attribute token [rw] OTP token required by the institution
|
10
|
+
# @!attribute encryption_key [rw] Custom encryption key
|
11
|
+
class LinkOptions < Faraday::Options.new(
|
12
|
+
:access_mode,
|
13
|
+
:token,
|
14
|
+
:encryption_key
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @!class AccountOptions < Faraday::Options
|
19
|
+
# Contains the configurable properties for an Account
|
20
|
+
# @!attribute save_data [rw] Should data be persisted or not.
|
21
|
+
# @!attribute token [rw] OTP token required by the institution
|
22
|
+
# @!attribute encryption_key [rw] Custom encryption key
|
23
|
+
class AccountOptions < Faraday::Options.new(
|
24
|
+
:save_data,
|
25
|
+
:token,
|
26
|
+
:encryption_key
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @!class TransactionOptions < Faraday::Options
|
31
|
+
# Contains configurable properties for a Transaction
|
32
|
+
# @!attribute date_to [rw] Date string (YYYY-MM-DD)
|
33
|
+
# @!attribute account [rw] Account ID (UUID)
|
34
|
+
# @!attribute save_data [rw] Should data be persisted or not.
|
35
|
+
# @!attribute token [rw] OTP token required by the institution
|
36
|
+
# @!attribute encryption_key [rw] Custom encryption key
|
37
|
+
class TransactionOptions < Faraday::Options.new(
|
38
|
+
:date_to,
|
39
|
+
:account,
|
40
|
+
:token,
|
41
|
+
:encryption_key,
|
42
|
+
:save_data
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @!class OwnerOptions < Faraday::Options
|
47
|
+
# Contains configurable properties of an Owner
|
48
|
+
# @!attribute save_data [rw] Should data be persisted or not.
|
49
|
+
# @!attribute token [rw] OTP token required by the institution
|
50
|
+
# @!attribute encryption_key [rw] Custom encryption key
|
51
|
+
class OwnerOptions < Faraday::Options.new(:token, :encryption_key, :save_data)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @!class BalanceOptions < Faraday::Options
|
55
|
+
# Contains configurable properties of a Balance
|
56
|
+
# @!attribute date_to [rw] Date string (YYYY-MM-DD)
|
57
|
+
# @!attribute account [rw] Account ID (UUID)
|
58
|
+
# @!attribute save_data [rw] Should data be persisted or not.
|
59
|
+
# @!attribute token [rw] OTP token required by the institution
|
60
|
+
# @!attribute encryption_key [rw] Custom encryption key
|
61
|
+
class BalanceOptions < Faraday::Options.new(
|
62
|
+
:date_to,
|
63
|
+
:account,
|
64
|
+
:token,
|
65
|
+
:encryption_key,
|
66
|
+
:save_data
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @!class StatementOptions < Faraday::Options
|
71
|
+
# Contains configurable properties of a Statement
|
72
|
+
# @!attribute save_data [rw] Should data be persisted or not.
|
73
|
+
# @!attribute token [rw] OTP token required by the institution
|
74
|
+
# @!attribute encryption_key [rw] Custom encryption key
|
75
|
+
# @!attribute attach_pdf [rw] Should the PDF file be included in the
|
76
|
+
# response or not.
|
77
|
+
class StatementOptions < Faraday::Options.new(
|
78
|
+
:token,
|
79
|
+
:encryption_key,
|
80
|
+
:save_data,
|
81
|
+
:attach_pdf
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
# @!class InvoiceOptions < Faraday::Options
|
86
|
+
# Contains configurable properties of an Invoice
|
87
|
+
# @!attribute save_data [rw] Should data be persisted or not.
|
88
|
+
# @!attribute token [rw] OTP token required by the institution
|
89
|
+
# @!attribute encryption_key [rw] Custom encryption key
|
90
|
+
# @!attribute attach_xml [rw] Should the XML file be included in the
|
91
|
+
# response or not.
|
92
|
+
class InvoiceOptions < Faraday::Options.new(
|
93
|
+
:save_data,
|
94
|
+
:token,
|
95
|
+
:encryption_key,
|
96
|
+
:attach_xml
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
# @!class TaxReturnOptions < Faraday::Options
|
101
|
+
# Contains configurable properties of a TaxReturn
|
102
|
+
# @!attribute save_data [rw] Should data be persisted or not.
|
103
|
+
# @!attribute token [rw] OTP token required by the institution
|
104
|
+
# @!attribute encryption_key [rw] Custom encryption key
|
105
|
+
# @!attribute attach_pdf [rw] Should the PDF file be included in the
|
106
|
+
# response or not.
|
107
|
+
class TaxReturnOptions < Faraday::Options.new(
|
108
|
+
:token,
|
109
|
+
:encryption_key,
|
110
|
+
:save_data,
|
111
|
+
:attach_pdf
|
112
|
+
)
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,343 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'belvo/options'
|
5
|
+
|
6
|
+
module Belvo
|
7
|
+
# Represents a consumable REST resource from Belvo API
|
8
|
+
class Resource
|
9
|
+
# Resource API endpoint
|
10
|
+
# @return [String] the API endpoint
|
11
|
+
attr_reader :endpoint
|
12
|
+
|
13
|
+
# @param session [APISession] current Belvo API session
|
14
|
+
def initialize(session)
|
15
|
+
@session = session
|
16
|
+
end
|
17
|
+
|
18
|
+
# Remove nil values from a request body
|
19
|
+
# @param body [Hash] request body
|
20
|
+
# @return [Hash] body without nil values
|
21
|
+
def clean(body:)
|
22
|
+
body.delete_if { |_key, value| value.nil? }
|
23
|
+
end
|
24
|
+
|
25
|
+
# List all results
|
26
|
+
# @return [Array]
|
27
|
+
# @raise [RequestError] If response code is different than 2XX
|
28
|
+
def list
|
29
|
+
results = []
|
30
|
+
@session.list(@endpoint) { |item| results.push item }
|
31
|
+
results
|
32
|
+
end
|
33
|
+
|
34
|
+
# Show specific resource details
|
35
|
+
# @param id [String] Resource UUID
|
36
|
+
# @return [Hash]
|
37
|
+
# @raise [RequestError] If response code is different than 2XX
|
38
|
+
def detail(id:)
|
39
|
+
@session.detail(@endpoint, id)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Delete existing resource
|
43
|
+
# @param id [String] Resource UUID
|
44
|
+
# @return [Boolean] true if resource is successfully deleted else false
|
45
|
+
def delete(id:)
|
46
|
+
@session.delete(@endpoint, id)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Resume data extraction session. Use this method after you have received a
|
50
|
+
# HTTP 428 response.
|
51
|
+
# @param session_id [String] Session UUID included in the 428 response
|
52
|
+
# @param link [String, nil] Link UUID
|
53
|
+
# @raise [RequestError] If response code is different than 2XX
|
54
|
+
def resume(session_id:, token:, link: nil)
|
55
|
+
data = { session: session_id, token: token, link: link }
|
56
|
+
@session.patch(@endpoint, data)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# A Link is a set of credentials associated to a end-user access
|
61
|
+
class Link < Resource
|
62
|
+
class AccessMode
|
63
|
+
# Use single to do ad hoc one-time requests
|
64
|
+
SINGLE = 'single'
|
65
|
+
# Use recurrent to have Belvo refresh your link data on a daily basis
|
66
|
+
RECURRENT = 'recurrent'
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize(session)
|
70
|
+
super(session)
|
71
|
+
@endpoint = 'links/'
|
72
|
+
end
|
73
|
+
|
74
|
+
# Register a new link
|
75
|
+
# @param institution [String] Institution name
|
76
|
+
# @param username [String] End-user username
|
77
|
+
# @param password [String] End-user password
|
78
|
+
# @param password2 [String, nil] End-user secondary password, if any
|
79
|
+
# @param options [LinkOptions] Configurable properties
|
80
|
+
# @return [Hash] created link details
|
81
|
+
# @raise [RequestError] If response code is different than 2XX
|
82
|
+
def register(
|
83
|
+
institution:,
|
84
|
+
username:,
|
85
|
+
password:,
|
86
|
+
password2: nil,
|
87
|
+
options: nil
|
88
|
+
)
|
89
|
+
options = LinkOptions.from(options)
|
90
|
+
body = {
|
91
|
+
institution: institution,
|
92
|
+
username: username,
|
93
|
+
password: password,
|
94
|
+
password2: password2,
|
95
|
+
token: options.token,
|
96
|
+
encryption_key: options.encryption_key,
|
97
|
+
access_mode: options.access_mode || AccessMode::SINGLE
|
98
|
+
}.merge(options)
|
99
|
+
body = clean body: body
|
100
|
+
@session.post(@endpoint, body)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Allows to change password, password2 or setting a custom encryption key
|
104
|
+
# @param id [String] Link UUID
|
105
|
+
# @param password [String] End-user password
|
106
|
+
# @param password2 [String, nil] End-user secondary password, if any
|
107
|
+
# @param options [LinkOptions] Configurable properties
|
108
|
+
# @return [Hash] link details
|
109
|
+
# @raise [RequestError] If response code is different than 2XX
|
110
|
+
def update(id:, password:, password2: nil, options: nil)
|
111
|
+
options = LinkOptions.from(options)
|
112
|
+
body = {
|
113
|
+
password: password,
|
114
|
+
password2: password2,
|
115
|
+
token: options.token,
|
116
|
+
encryption_key: options.encryption_key
|
117
|
+
}.merge(options)
|
118
|
+
body = clean body: body
|
119
|
+
@session.put(@endpoint, id, body)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# An Account is the representation of a bank account inside a financial
|
124
|
+
# institution.
|
125
|
+
class Account < Resource
|
126
|
+
def initialize(session)
|
127
|
+
super(session)
|
128
|
+
@endpoint = 'accounts/'
|
129
|
+
end
|
130
|
+
|
131
|
+
# Retrieve accounts from an existing link
|
132
|
+
# @param link [String] Link UUID
|
133
|
+
# @param options [AccountOptions] Configurable properties
|
134
|
+
# @return [Hash] created link details
|
135
|
+
# @raise [RequestError] If response code is different than 2XX
|
136
|
+
def retrieve(link:, options: nil)
|
137
|
+
options = AccountOptions.from(options)
|
138
|
+
body = {
|
139
|
+
link: link,
|
140
|
+
token: options.token,
|
141
|
+
encryption_key: options.encryption_key,
|
142
|
+
save_data: options.save_data || true
|
143
|
+
}.merge(options)
|
144
|
+
body = clean body: body
|
145
|
+
@session.post(@endpoint, body)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# A Transaction contains the detailed information of each movement inside an
|
150
|
+
# Account.
|
151
|
+
class Transaction < Resource
|
152
|
+
def initialize(session)
|
153
|
+
super(session)
|
154
|
+
@endpoint = 'transactions/'
|
155
|
+
end
|
156
|
+
|
157
|
+
# Retrieve transactions from an existing link
|
158
|
+
# @param link [String] Link UUID
|
159
|
+
# @param date_from [String] Date string (YYYY-MM-DD)
|
160
|
+
# @param options [TransactionOptions] Configurable properties
|
161
|
+
# @return [Hash] created link details
|
162
|
+
# @raise [RequestError] If response code is different than 2XX
|
163
|
+
def retrieve(link:, date_from:, options: nil)
|
164
|
+
options = TransactionOptions.from(options)
|
165
|
+
date_to = options.date_to || Date.today.to_s
|
166
|
+
body = {
|
167
|
+
link: link,
|
168
|
+
date_from: date_from,
|
169
|
+
date_to: date_to,
|
170
|
+
token: options.token,
|
171
|
+
account: options.account,
|
172
|
+
encryption_key: options.encryption_key,
|
173
|
+
save_data: options.save_data || true
|
174
|
+
}.merge(options)
|
175
|
+
body = clean body: body
|
176
|
+
@session.post(@endpoint, body)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# An Owner represents the person who has access to a Link and is the owner
|
181
|
+
# of all the Accounts inside the Link
|
182
|
+
class Owner < Resource
|
183
|
+
def initialize(session)
|
184
|
+
super(session)
|
185
|
+
@endpoint = 'owners/'
|
186
|
+
end
|
187
|
+
|
188
|
+
# Retrieve owners from an existing link
|
189
|
+
# @param link [String] Link UUID
|
190
|
+
# @param options [OwnerOptions] Configurable properties
|
191
|
+
# @return [Hash] created link details
|
192
|
+
# @raise [RequestError] If response code is different than 2XX
|
193
|
+
def retrieve(link:, options: nil)
|
194
|
+
options = OwnerOptions.from(options)
|
195
|
+
body = {
|
196
|
+
link: link,
|
197
|
+
token: options.token,
|
198
|
+
encryption_key: options.encryption_key,
|
199
|
+
save_data: options.save_data || true
|
200
|
+
}.merge(options)
|
201
|
+
body = clean body: body
|
202
|
+
@session.post(@endpoint, body)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# A Balance represents the financial status of an Account at a given time.
|
207
|
+
class Balance < Resource
|
208
|
+
def initialize(session)
|
209
|
+
super(session)
|
210
|
+
@endpoint = 'balances/'
|
211
|
+
end
|
212
|
+
|
213
|
+
# Retrieve balances from a specific account or all accounts from a
|
214
|
+
# specific link
|
215
|
+
# @param link [String] Link UUID
|
216
|
+
# @param date_from [String] Date string (YYYY-MM-DD)
|
217
|
+
# @param options [BalanceOptions] Configurable properties
|
218
|
+
# @return [Hash] created link details
|
219
|
+
# @raise [RequestError] If response code is different than 2XX
|
220
|
+
def retrieve(link:, date_from:, options: nil)
|
221
|
+
options = BalanceOptions.from(options)
|
222
|
+
date_to = options.date_to || Date.today.to_s
|
223
|
+
body = {
|
224
|
+
link: link,
|
225
|
+
date_from: date_from,
|
226
|
+
date_to: date_to,
|
227
|
+
token: options.token,
|
228
|
+
account: options.account,
|
229
|
+
encryption_key: options.encryption_key,
|
230
|
+
save_data: options.save_data || true
|
231
|
+
}.merge(options)
|
232
|
+
body = clean body: body
|
233
|
+
@session.post(@endpoint, body)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# A Statement contains a resume of monthly Transactions inside an Account.
|
238
|
+
class Statement < Resource
|
239
|
+
def initialize(session)
|
240
|
+
super(session)
|
241
|
+
@endpoint = 'statements/'
|
242
|
+
end
|
243
|
+
|
244
|
+
# Retrieve statements information from a specific banking link.
|
245
|
+
# @param link [String] Link UUID
|
246
|
+
# @param year [Integer]
|
247
|
+
# @param month [Integer]
|
248
|
+
# @param options [StatementOptions] Configurable properties
|
249
|
+
# @return [Hash] created link details
|
250
|
+
# @raise [RequestError] If response code is different than 2XX
|
251
|
+
def retrieve(link:, account:, year:, month:, options: nil)
|
252
|
+
options = StatementOptions.from(options)
|
253
|
+
body = {
|
254
|
+
link: link,
|
255
|
+
account: account,
|
256
|
+
year: year,
|
257
|
+
month: month,
|
258
|
+
token: options.token,
|
259
|
+
encryption_key: options.encryption_key,
|
260
|
+
save_data: options.save_data || true,
|
261
|
+
attach_pdf: options.attach_pdf
|
262
|
+
}.merge(options)
|
263
|
+
body = clean body: body
|
264
|
+
@session.post(@endpoint, body)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# An Invoice is the representation of an electronic invoice, that can be
|
269
|
+
# received or sent, by a business or an individual and has been uploaded
|
270
|
+
# to the fiscal institution website
|
271
|
+
class Invoice < Resource
|
272
|
+
def initialize(session)
|
273
|
+
super(session)
|
274
|
+
@endpoint = 'invoices/'
|
275
|
+
end
|
276
|
+
|
277
|
+
# @param link [String] Link UUID
|
278
|
+
# @param date_from [String] Date string (YYYY-MM-DD)
|
279
|
+
# @param date_to [String] Date string (YYYY-MM-DD)
|
280
|
+
# @param options [InvoiceOptions] Configurable properties
|
281
|
+
# @return [Hash] created link details
|
282
|
+
# @raise [RequestError] If response code is different than 2XX
|
283
|
+
def retrieve(link:, date_from:, date_to:, type:, options: nil)
|
284
|
+
options = InvoiceOptions.from(options)
|
285
|
+
body = {
|
286
|
+
link: link,
|
287
|
+
date_from: date_from,
|
288
|
+
date_to: date_to,
|
289
|
+
type: type,
|
290
|
+
token: options.token,
|
291
|
+
encryption_key: options.encryption_key,
|
292
|
+
save_data: options.save_data || true,
|
293
|
+
attach_xml: options.attach_xml
|
294
|
+
}.merge(options)
|
295
|
+
body = clean body: body
|
296
|
+
@session.post(@endpoint, body)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# A Tax return is the representation of the tax return document sent every
|
301
|
+
# year by a person or a business to the tax authority in the country.
|
302
|
+
class TaxReturn < Resource
|
303
|
+
def initialize(session)
|
304
|
+
super(session)
|
305
|
+
@endpoint = 'tax-returns/'
|
306
|
+
end
|
307
|
+
|
308
|
+
# Retrieve tax returns information from a specific fiscal link.
|
309
|
+
# @param link [String] Link UUID
|
310
|
+
# @param year_from [Integer]
|
311
|
+
# @param year_to [Integer]
|
312
|
+
# @param options [TaxReturnOptions] Configurable properties
|
313
|
+
# @return [Hash] created link details
|
314
|
+
# @raise [RequestError] If response code is different than 2XX
|
315
|
+
def retrieve(link:, year_from:, year_to:, options: nil)
|
316
|
+
options = TaxReturnOptions.from(options)
|
317
|
+
body = {
|
318
|
+
link: link,
|
319
|
+
year_from: year_from,
|
320
|
+
year_to: year_to,
|
321
|
+
token: options.token,
|
322
|
+
encryption_key: options.encryption_key,
|
323
|
+
save_data: options.save_data || true,
|
324
|
+
attach_pdf: options.attach_pdf
|
325
|
+
}.merge(options)
|
326
|
+
body = clean body: body
|
327
|
+
@session.post(@endpoint, body)
|
328
|
+
end
|
329
|
+
|
330
|
+
def resume(_session_id, _token, _link: nil)
|
331
|
+
raise NotImplementedError 'TaxReturn does not support resuming a session.'
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
# An Institution is an entity that Belvo can access information from. It can
|
336
|
+
# be a bank or fiscal type of institutions such as the SAT in Mexico.
|
337
|
+
class Institution < Resource
|
338
|
+
def initialize(session)
|
339
|
+
super(session)
|
340
|
+
@endpoint = 'institutions/'
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|