bridge_bankin 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,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ module API
5
+ class Error < StandardError
6
+ def initialize(code, response_body = {})
7
+ @payload = response_body
8
+ @code = code
9
+ @type = payload[:type]
10
+ @documentation_url = payload[:documentation_url]
11
+
12
+ super(payload[:message])
13
+ end
14
+
15
+ attr_reader :payload, :code, :type, :documentation_url
16
+ end
17
+
18
+ class BadRequestError < Error; end
19
+
20
+ class UnauthorizedError < Error; end
21
+
22
+ class ForbiddenError < Error; end
23
+
24
+ class NotFoundError < Error; end
25
+
26
+ class ConflictError < Error; end
27
+
28
+ class UnsupportedMediaTypeError < Error; end
29
+
30
+ class UnprocessableEntityError < Error; end
31
+
32
+ class TooManyRequestsError < Error; end
33
+
34
+ class InternalServerError < Error; end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ module API
5
+ module Resource
6
+ def protected_resource(access_token)
7
+ api_client.access_token = access_token
8
+ yield
9
+ end
10
+
11
+ private
12
+
13
+ def api_client
14
+ @api_client ||= API::Client.new
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module BridgeBankin
6
+ class Authorization
7
+ attr_reader :access_token, :expires_at
8
+
9
+ def initialize(access_token, expires_at)
10
+ @access_token = access_token
11
+ @expires_at = Time.parse(expires_at)
12
+ end
13
+
14
+ class << self
15
+ include API::Resource
16
+
17
+ def generate_token(email:, password:)
18
+ response = api_client.post("/v2/authenticate", email: email, password: password)
19
+ new(response[:access_token], response[:expires_at])
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ class Bank < BridgeObject
5
+ RESOURCE_TYPE = "bank"
6
+
7
+ class << self
8
+ include API::Resource
9
+
10
+ def list(**params)
11
+ data = api_client.get("/v2/banks", params)
12
+ convert_to_bridge_object(data)
13
+ end
14
+
15
+ def find(id:, **params)
16
+ data = api_client.get("/v2/banks/#{id}", params)
17
+ convert_to_bridge_object(data)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ class BridgeObject
5
+ HIDDEN_ATTRIBUTES = %i[resource_type resource_uri].freeze
6
+
7
+ def initialize(**attrs)
8
+ define_instance_variables(attrs)
9
+ end
10
+
11
+ class << self
12
+ def convert_to_bridge_object(**data)
13
+ if data[:resources]
14
+ data[:resources].map { |resource| convert_to_bridge_object(resource) }
15
+ elsif data.is_a?(Array)
16
+ data.map { |val| convert_to_bridge_object(val) }
17
+ else
18
+ object_from_resource_type(data)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def object_classes
25
+ @object_classes ||= ObjectTypes.resource_types_to_classes
26
+ end
27
+
28
+ def object_from_resource_type(data)
29
+ object_classes.fetch(data[:resource_type], BridgeObject).new(data)
30
+ end
31
+ end
32
+
33
+ def to_hash
34
+ instance_variables.each_with_object({}) do |var, hash|
35
+ hash[var.to_s.delete("@")] =
36
+ case instance_variable_get(var)
37
+ when BridgeObject
38
+ instance_variable_get(var).to_hash
39
+ when Array
40
+ instance_variable_get(var).map { |val| val.is_a?(BridgeObject) ? val.to_hash : val }
41
+ else
42
+ instance_variable_get(var)
43
+ end
44
+ end.transform_keys!(&:to_sym)
45
+ end
46
+
47
+ def to_json(*_args)
48
+ to_hash.to_json
49
+ end
50
+
51
+ def ==(other)
52
+ other.is_a?(BridgeObject) && to_hash == other.to_hash
53
+ end
54
+
55
+ private
56
+
57
+ def define_instance_variables(attrs)
58
+ attrs.each do |key, value|
59
+ next if HIDDEN_ATTRIBUTES.include?(key)
60
+
61
+ handle_values_types(key, value) do |parsed_value|
62
+ instance_variable_set("@#{key}".to_sym, parsed_value)
63
+ self.class.class_eval { attr_reader key }
64
+ end
65
+ end
66
+ end
67
+
68
+ def handle_values_types(key, value)
69
+ yield(
70
+ case value
71
+ when Array
72
+ handle_array_values(value)
73
+ when Hash
74
+ handle_hash_values(value)
75
+ when String
76
+ handle_time_values(key, value)
77
+ else
78
+ value
79
+ end
80
+ )
81
+ end
82
+
83
+ def handle_array_values(array)
84
+ array.map do |value|
85
+ next value unless value.is_a?(Hash)
86
+
87
+ handle_hash_values(value)
88
+ end
89
+ end
90
+
91
+ def handle_hash_values(hash)
92
+ self.class.convert_to_bridge_object(hash)
93
+ end
94
+
95
+ def handle_time_values(key, value)
96
+ if key == :date
97
+ Date.parse(value)
98
+ elsif key.to_s.match?(/_at$/)
99
+ Time.parse(value)
100
+ else
101
+ value
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ class Category < BridgeObject
5
+ RESOURCE_TYPE = "category"
6
+
7
+ class << self
8
+ include API::Resource
9
+
10
+ def list(**params)
11
+ data = api_client.get("/v2/categories", params)
12
+ convert_to_bridge_object(data)
13
+ end
14
+
15
+ def find(id:, **params)
16
+ data = api_client.get("/v2/categories/#{id}", params)
17
+ convert_to_bridge_object(data)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ def self.configuration
5
+ @configuration ||= Configuration.new
6
+ end
7
+
8
+ def self.configuration=(config)
9
+ @configuration = config
10
+ end
11
+
12
+ def self.configure
13
+ yield configuration
14
+ end
15
+
16
+ class Configuration
17
+ attr_reader :api_base_url, :api_version
18
+ attr_accessor :api_client_id, :api_client_secret
19
+
20
+ def initialize
21
+ @api_base_url = "https://sync.bankin.com"
22
+ @api_version = "2019-02-18"
23
+ @api_client_id = "d16099aec29e445dbb31cf3966b3821e"
24
+ @api_client_secret = "HEb73vHEGB4Hunv5OMXFUDNIgNonYJ89YaHHRSyidVgCPbCtFWqtED5fZYObA0lm"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ class Connect < BridgeObject
5
+ class << self
6
+ include API::Resource
7
+
8
+ def connect_item(access_token:, **params)
9
+ protected_resource(access_token) do
10
+ data = api_client.get("/v2/connect/items/add/url", params)
11
+ convert_to_bridge_object(data)
12
+ end
13
+ end
14
+
15
+ def connect_item_with_iban(access_token:, **params)
16
+ protected_resource(access_token) do
17
+ data = api_client.post("/v2/connect/items/add/url", params)
18
+ convert_to_bridge_object(data)
19
+ end
20
+ end
21
+
22
+ def edit_item(access_token:, **params)
23
+ protected_resource(access_token) do
24
+ data = api_client.get("/v2/connect/items/edit/url", params)
25
+ convert_to_bridge_object(data)
26
+ end
27
+ end
28
+
29
+ def item_sync(access_token:, **params)
30
+ protected_resource(access_token) do
31
+ data = api_client.get("/v2/connect/items/sync", params)
32
+ convert_to_bridge_object(data)
33
+ end
34
+ end
35
+
36
+ def validate_email(access_token:, **params)
37
+ protected_resource(access_token) do
38
+ data = api_client.get("/v2/connect/users/email/confirmation/url", params)
39
+ convert_to_bridge_object(data)
40
+ end
41
+ end
42
+
43
+ def validate_pro_items(access_token:, **params)
44
+ protected_resource(access_token) do
45
+ data = api_client.get("/v2/connect/items/pro/confirmation/url", params)
46
+ convert_to_bridge_object(data)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ class Insight < BridgeObject
5
+ class << self
6
+ include API::Resource
7
+
8
+ def categories_insights(access_token:, **params)
9
+ protected_resource(access_token) do
10
+ data = api_client.get("/v2/insights/category", params)
11
+ convert_to_bridge_object(data)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ class Item < BridgeObject
5
+ RESOURCE_TYPE = "item"
6
+
7
+ # TODO: Add support of item statuses
8
+
9
+ class << self
10
+ include API::Resource
11
+
12
+ def list(access_token:, **params)
13
+ protected_resource(access_token) do
14
+ data = api_client.get("/v2/items", params)
15
+ convert_to_bridge_object(data)
16
+ end
17
+ end
18
+
19
+ def find(id:, access_token:, **params)
20
+ protected_resource(access_token) do
21
+ data = api_client.get("/v2/items/#{id}", params)
22
+ convert_to_bridge_object(data)
23
+ end
24
+ end
25
+
26
+ def refresh(id:, access_token:, **params)
27
+ protected_resource(access_token) do
28
+ data = api_client.post("/v2/items/#{id}/refresh", params)
29
+ convert_to_bridge_object(data)
30
+ end
31
+ end
32
+
33
+ def refresh_status(id:, access_token:, **params)
34
+ protected_resource(access_token) do
35
+ data = api_client.get("/v2/items/#{id}/refresh/status", params)
36
+ convert_to_bridge_object(data)
37
+ end
38
+ end
39
+
40
+ def delete(id:, access_token:, **params)
41
+ protected_resource(access_token) do
42
+ data = api_client.delete("/v2/items/#{id}", params)
43
+ convert_to_bridge_object(data)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ module ObjectTypes
5
+ def self.resource_types_to_classes
6
+ {
7
+ Account::RESOURCE_TYPE => Account,
8
+ Bank::RESOURCE_TYPE => Bank,
9
+ Category::RESOURCE_TYPE => Category,
10
+ Item::RESOURCE_TYPE => Item,
11
+ Stock::RESOURCE_TYPE => Stock,
12
+ Transaction::RESOURCE_TYPE => Transaction,
13
+ Transfer::RESOURCE_TYPE => Transfer,
14
+ User::RESOURCE_TYPE => User
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bridge_bankin/authorization"
4
+ require "bridge_bankin/account"
5
+ require "bridge_bankin/category"
6
+ require "bridge_bankin/stock"
7
+ require "bridge_bankin/bank"
8
+ require "bridge_bankin/user"
9
+ require "bridge_bankin/connect"
10
+ require "bridge_bankin/item"
11
+ require "bridge_bankin/transaction"
12
+ require "bridge_bankin/transfer"
13
+ require "bridge_bankin/insight"
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ class Stock < BridgeObject
5
+ RESOURCE_TYPE = "stock"
6
+
7
+ class << self
8
+ include API::Resource
9
+
10
+ def list(**params)
11
+ data = api_client.get("/v2/stocks", params)
12
+ convert_to_bridge_object(data)
13
+ end
14
+
15
+ def list_updated(**params)
16
+ data = api_client.get("/v2/stocks/updated", params)
17
+ convert_to_bridge_object(data)
18
+ end
19
+
20
+ def find(id:, **params)
21
+ data = api_client.get("/v2/stocks/#{id}", params)
22
+ convert_to_bridge_object(data)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BridgeBankin
4
+ class Transaction < BridgeObject
5
+ RESOURCE_TYPE = "transaction"
6
+
7
+ class << self
8
+ include API::Resource
9
+
10
+ def list(access_token:, **params)
11
+ protected_resource(access_token) do
12
+ data = api_client.get("/v2/transactions", params)
13
+ convert_to_bridge_object(data)
14
+ end
15
+ end
16
+
17
+ def list_updated(access_token:, **params)
18
+ protected_resource(access_token) do
19
+ data = api_client.get("/v2/transactions/updated", params)
20
+ convert_to_bridge_object(data)
21
+ end
22
+ end
23
+
24
+ def find(id:, access_token:, **params)
25
+ protected_resource(access_token) do
26
+ data = api_client.get("/v2/transactions/#{id}", params)
27
+ convert_to_bridge_object(data)
28
+ end
29
+ end
30
+
31
+ def list_by_account(account_id:, access_token:, **params)
32
+ protected_resource(access_token) do
33
+ data = api_client.get("/v2/accounts/#{account_id}/transactions", params)
34
+ convert_to_bridge_object(data)
35
+ end
36
+ end
37
+
38
+ def list_updated_by_account(account_id:, access_token:, **params)
39
+ protected_resource(access_token) do
40
+ data = api_client.get("/v2/accounts/#{account_id}/transactions/updated", params)
41
+ convert_to_bridge_object(data)
42
+ end
43
+ end
44
+
45
+ def list_by_iban(access_token:, **params)
46
+ protected_resource(access_token) do
47
+ data = api_client.post("/v2/transactions/search", params)
48
+ convert_to_bridge_object(data)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end