fintoc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ module Fintoc
2
+ module Constants
3
+ FIELDSUBS = [%w[id id_], %w[type type_]].freeze
4
+ GENERAL_DOC_URL = "https://fintoc.com/docs"
5
+ SCHEME = "https://"
6
+ BASE_URL = "api.fintoc.com/v1/"
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ require 'fintoc/constants'
2
+
3
+ module Fintoc
4
+ module Errors
5
+ class FintocError < StandardError
6
+ def initialize(message, doc_url = Fintoc::Constants::GENERAL_DOC_URL)
7
+ @message = message
8
+ @doc_url = doc_url
9
+ end
10
+
11
+ def message
12
+ "\n#{@message}\n Please check the docs at: #{@doc_url}"
13
+ end
14
+
15
+ def to_s
16
+ message
17
+ end
18
+ end
19
+ class InvalidRequestError < FintocError; end
20
+ class LinkError < FintocError; end
21
+ class AuthenticationError < FintocError; end
22
+ class InstitutionError < FintocError; end
23
+ class ApiError < FintocError; end
24
+ class MissingResourceError < FintocError; end
25
+ class InvalidLinkTokenError < FintocError; end
26
+ class InvalidUsernameError < FintocError; end
27
+ class InvalidHolderTypeError < FintocError; end
28
+ class MissingParameterError < FintocError; end
29
+ class EmptyStringError < FintocError; end
30
+ class UnrecognizedRequestError < FintocError; end
31
+ class InvalidDateError < FintocError; end
32
+ class InvalidCredentialsError < FintocError; end
33
+ class LockedCredentialsError < FintocError; end
34
+ class InvalidApiKeyError < FintocError; end
35
+ class UnavailableInstitutionError < FintocError; end
36
+ class InternalServerError < FintocError; end
37
+ end
38
+ end
@@ -0,0 +1,84 @@
1
+ require 'tabulate'
2
+ require 'fintoc/utils'
3
+ require 'fintoc/resources/movement'
4
+ require 'fintoc/resources/balance'
5
+
6
+ module Fintoc
7
+ class Account
8
+ include Utils
9
+ attr_reader :id, :name, :holder_name, :currency, :type, :refreshed_at,
10
+ :official_name, :number, :holder_id, :balance, :movements
11
+ def initialize(
12
+ id:,
13
+ name:,
14
+ official_name:,
15
+ number:,
16
+ holder_id:,
17
+ holder_name:,
18
+ type:,
19
+ currency:,
20
+ refreshed_at: nil,
21
+ balance: nil,
22
+ movements: nil,
23
+ client: nil,
24
+ **
25
+ )
26
+ @id = id
27
+ @name = name
28
+ @official_name = official_name
29
+ @number = number
30
+ @holder_id = holder_id
31
+ @holder_name = holder_name
32
+ @type = type
33
+ @currency = currency
34
+ @refreshed_at = DateTime.iso8601(refreshed_at) if refreshed_at
35
+ @balance = Fintoc::Balance.new(**balance)
36
+ @movements = movements || []
37
+ @client = client
38
+ end
39
+
40
+ def update_balance
41
+ @balance = Fintoc::Balance.new(**get_account[:balance])
42
+ end
43
+
44
+ def get_movements(**params)
45
+ _get_movements(**params).lazy.map { |movement| Fintoc::Movement.new(**movement) }
46
+ end
47
+
48
+ def update_movements(**params)
49
+ @movements += get_movements(**params).to_a
50
+ @movements = @movements.uniq.sort_by(&:post_date)
51
+ end
52
+
53
+ def show_movements(rows = 5)
54
+ puts("This account has #{Utils.pluralize(@movements.size, 'movement')}.")
55
+
56
+ return unless @movements.any?
57
+
58
+ movements = @movements.to_a.slice(0, rows)
59
+ .map.with_index do |mov, index|
60
+ [index + 1, mov.amount, mov.currency, mov.description, mov.locale_date]
61
+ end
62
+ headers = ['#', 'Amount', 'Currency', 'Description', 'Date']
63
+ puts
64
+ puts tabulate(headers, movements, indent: 4, style: 'fancy')
65
+ end
66
+
67
+ def to_s
68
+ "💰 #{@holder_name}’s #{@name} #{@balance}"
69
+ end
70
+
71
+ private
72
+
73
+ def get_account
74
+ @client.get.call("accounts/#{@id}")
75
+ end
76
+
77
+ def _get_movements(**params)
78
+ first = @client.get.call("accounts/#{@id}/movements", **params)
79
+ return first if params.empty?
80
+
81
+ first + Utils.flatten(@client.fetch_next)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fintoc
4
+ class Balance
5
+ attr_reader :available, :current, :limit
6
+ def initialize(available:, current:, limit:)
7
+ @available = available
8
+ @current = current
9
+ @limit = limit
10
+ end
11
+
12
+ def id
13
+ object_id
14
+ end
15
+
16
+ def to_s
17
+ "#{@available} (#{@current})"
18
+ end
19
+
20
+ def inspect
21
+ "<Balance #{@available} (#{@current})>"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ module Fintoc
2
+ class Institution
3
+ attr_reader :id, :name, :country
4
+ def initialize(id:, name:, country:, **)
5
+ @id = id
6
+ @name = name
7
+ @country = country
8
+ end
9
+
10
+ def to_s
11
+ "🏦 #{@name}"
12
+ end
13
+
14
+ def inspect
15
+ "<Institution #{@name}>"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,83 @@
1
+ require 'date'
2
+ require 'tabulate'
3
+ require 'fintoc/utils'
4
+ require 'fintoc/resources/account'
5
+ require 'fintoc/resources/institution'
6
+ require 'tabulate'
7
+
8
+ module Fintoc
9
+ class Link
10
+ attr_reader :id, :username, :holder_type, :institution, :created_at, :mode,
11
+ :accounts, :link_token
12
+ include Utils
13
+ def initialize(
14
+ id:,
15
+ username:,
16
+ holder_type:,
17
+ institution:,
18
+ created_at:,
19
+ mode:,
20
+ accounts: nil,
21
+ link_token: nil,
22
+ client: nil,
23
+ **
24
+ )
25
+ @id = id
26
+ @username = username
27
+ @holder_type = holder_type
28
+ @institution = Fintoc::Institution.new(**institution)
29
+ @created_at = Date.iso8601(created_at)
30
+ @mode = mode
31
+ @accounts = if accounts.nil?
32
+ []
33
+ else
34
+ accounts.map { |data| Fintoc::Account.new(**data, client: client) }
35
+ end
36
+ @token = link_token
37
+ @client = client
38
+ end
39
+
40
+ def find_all(**kwargs)
41
+ raise 'You must provide *exactly one* account field.' if kwargs.size != 1
42
+
43
+ field, value = kwargs.to_a.first
44
+ @accounts.select do |account|
45
+ account.send(field.to_sym) == value
46
+ end
47
+ end
48
+
49
+ def find(**kwargs)
50
+ results = find_all(**kwargs)
51
+ results.any? ? results.first : nil
52
+ end
53
+
54
+ def show_accounts(rows = 5)
55
+ puts "This links has #{Utils.plurlize(@accounts.size, 'account')}"
56
+
57
+ return unless @accounts.any?
58
+
59
+ accounts = @accounts.to_a.slice(0, rows)
60
+ .map.with_index do |acc, index|
61
+ [index + 1, acc.name, acc.holder_name, account.currency]
62
+ end
63
+ headers = ['#', 'Name', 'Holder', 'Currency']
64
+ puts
65
+ puts tabulate(headers, accounts, indent: 4, style: 'fancy')
66
+ end
67
+
68
+ def update_accounts
69
+ @accounts.each do |account|
70
+ account.update_balance
71
+ account.update_movements
72
+ end
73
+ end
74
+
75
+ def delete
76
+ @client.delete_link(@id)
77
+ end
78
+
79
+ def to_s
80
+ "<#{@username}@#{@institution.name}> 🔗 <Fintoc>"
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,55 @@
1
+ require 'date'
2
+ require 'fintoc/resources/transfer_account'
3
+
4
+ module Fintoc
5
+ class Movement
6
+ attr_reader :id, :amount, :currency, :description, :reference_id,
7
+ :post_date, :transaction_date, :type, :recipient_account,
8
+ :sender_account, :account, :comment
9
+
10
+ def initialize(
11
+ id:,
12
+ amount:,
13
+ currency:,
14
+ description:,
15
+ post_date:,
16
+ transaction_date:,
17
+ type:,
18
+ reference_id:,
19
+ recipient_account:,
20
+ sender_account:,
21
+ comment:,
22
+ **
23
+ )
24
+ @id = id
25
+ @amount = amount
26
+ @currency = currency
27
+ @description = description
28
+ @post_date = DateTime.iso8601(post_date)
29
+ @transaction_date = DateTime.iso8601(transaction_date) if transaction_date
30
+ @type = type
31
+ @reference_id = reference_id
32
+ @recipient_account = Fintoc::TransferAccount.new(**recipient_account) if recipient_account
33
+ @sender_account = Fintoc::TransferAccount.new(**sender_account) if sender_account
34
+ @comment = comment
35
+ end
36
+
37
+ def ==(other)
38
+ @id = other.id
39
+ end
40
+
41
+ alias eql? ==
42
+
43
+ def hash
44
+ @id.hash
45
+ end
46
+
47
+ def locale_date
48
+ @post_date.strftime('%x')
49
+ end
50
+
51
+ def to_s
52
+ "#{@amount} (#{@description} @ #{locale_date})"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,22 @@
1
+ require 'fintoc/resources/institution'
2
+
3
+ module Fintoc
4
+ class TransferAccount
5
+ attr_reader :holder_id, :holder_name, :number, :institution
6
+
7
+ def initialize(holder_id:, holder_name:, number:, institution:, **)
8
+ @holder_id = holder_id
9
+ @holder_name = holder_name
10
+ @number = number
11
+ @institution = institution && Fintoc::Institution.new(**institution)
12
+ end
13
+
14
+ def id
15
+ object_id
16
+ end
17
+
18
+ def to_s
19
+ @holder_id.to_s
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fintoc
4
+ # A handful of run-of-the-mill utilities
5
+ module Utils
6
+ extend self
7
+
8
+ # Get a flat Array out of a list of lists of Iterables(Enumerators)
9
+ #
10
+ def flatten(sequences)
11
+ Enumerator::Chain.new(*sequences).to_a
12
+ end
13
+
14
+ # If the key exists, you will get that key-value pair.
15
+ #
16
+ # @param dict_ [Hash] the hash to pick from
17
+ # @param key [String] the key to look at
18
+ # @return [Hash] the key-value pair or an empty hash
19
+ def pick(dict_, key)
20
+ key = key.to_sym
21
+ if dict_.key?(key)
22
+ { "#{key}": dict_[key] }
23
+ else
24
+ {}
25
+ end
26
+ end
27
+
28
+ # Get a pluralized noun with its appropiate quantifier
29
+ #
30
+ # @param amount [Integer]
31
+ # @param noun [String] the noun to pluralize
32
+ # @param suffix [String]
33
+ # @return [String]
34
+ def pluralize(amount, noun, suffix = 's')
35
+ quantifier = amount or 'no'
36
+ "#{quantifier} #{amount == 1 ? noun : noun + suffix}"
37
+ end
38
+
39
+ # Transform a snake-cased name to its pascal-cased version.
40
+ #
41
+ # @param name [String]
42
+ # @return [String]
43
+ def snake_to_pascal(name)
44
+ name.split('_').map(&:capitalize).join('')
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module Fintoc
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fintoc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Juan Ca Sardin
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-01-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: http
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tabulate
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.81.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.81.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-performance
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: vcr
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: The official Ruby client for the Fintoc API.
126
+ email:
127
+ - juan.carlos.sardin@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".rspec"
134
+ - ".rubocop.yml"
135
+ - ".travis.yml"
136
+ - CHANGELOG.md
137
+ - Gemfile
138
+ - Gemfile.lock
139
+ - LICENSE.MD
140
+ - README.md
141
+ - Rakefile
142
+ - bin/console
143
+ - bin/setup
144
+ - fintoc.gemspec
145
+ - lib/fintoc.rb
146
+ - lib/fintoc/client.rb
147
+ - lib/fintoc/constants.rb
148
+ - lib/fintoc/errors.rb
149
+ - lib/fintoc/resources/account.rb
150
+ - lib/fintoc/resources/balance.rb
151
+ - lib/fintoc/resources/institution.rb
152
+ - lib/fintoc/resources/link.rb
153
+ - lib/fintoc/resources/movement.rb
154
+ - lib/fintoc/resources/transfer_account.rb
155
+ - lib/fintoc/utils.rb
156
+ - lib/fintoc/version.rb
157
+ homepage: https://github.com/fintoc-com/fintoc-ruby
158
+ licenses: []
159
+ metadata:
160
+ homepage_uri: https://github.com/fintoc-com/fintoc-ruby
161
+ source_code_uri: https://github.com/fintoc-com/fintoc-ruby
162
+ post_install_message:
163
+ rdoc_options: []
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: 2.3.0
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubygems_version: 3.0.3
178
+ signing_key:
179
+ specification_version: 4
180
+ summary: The official Ruby client for the Fintoc API.
181
+ test_files: []