fintoc 0.1.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.
@@ -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: []