faithteams-api 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +11 -0
  3. data/.github/CODEOWNERS +1 -0
  4. data/.github/CONTRIBUTING.md +35 -0
  5. data/.github/PULL_REQUEST_TEMPLATE.md +8 -0
  6. data/.github/workflows/jeweler.yml +11 -0
  7. data/.github/workflows/puller.yml +17 -0
  8. data/.gitignore +16 -0
  9. data/.rspec +2 -0
  10. data/.rubocop.yml +227 -0
  11. data/.tool-versions +1 -0
  12. data/CHANGELOG.md +70 -0
  13. data/CODE_OF_CONDUCT.md +128 -0
  14. data/Gemfile +6 -0
  15. data/Gemfile.lock +171 -0
  16. data/Guardfile +50 -0
  17. data/LICENSE +21 -0
  18. data/README.md +85 -0
  19. data/Rakefile +8 -0
  20. data/bin/console +15 -0
  21. data/bin/setup +8 -0
  22. data/faithteams-api.gemspec +47 -0
  23. data/guides/api_client_interface.md +18 -0
  24. data/guides/release-process.md +11 -0
  25. data/lib/faithteams/api/v2/connection.rb +142 -0
  26. data/lib/faithteams/api/v2/entity/base.rb +36 -0
  27. data/lib/faithteams/api/v2/entity/batch.rb +68 -0
  28. data/lib/faithteams/api/v2/entity/contribution.rb +19 -0
  29. data/lib/faithteams/api/v2/entity/contribution_record.rb +137 -0
  30. data/lib/faithteams/api/v2/entity/contribution_type.rb +37 -0
  31. data/lib/faithteams/api/v2/entity/fund.rb +52 -0
  32. data/lib/faithteams/api/v2/entity/person.rb +77 -0
  33. data/lib/faithteams/api/v2/entity.rb +17 -0
  34. data/lib/faithteams/api/v2/error/no_search_parameter_provided.rb +12 -0
  35. data/lib/faithteams/api/v2/error/request.rb +46 -0
  36. data/lib/faithteams/api/v2/error.rb +13 -0
  37. data/lib/faithteams/api/v2/gateway.rb +51 -0
  38. data/lib/faithteams/api/v2/gateway_base.rb +25 -0
  39. data/lib/faithteams/api/v2/resource/base.rb +46 -0
  40. data/lib/faithteams/api/v2/resource/batch.rb +58 -0
  41. data/lib/faithteams/api/v2/resource/contribution.rb +39 -0
  42. data/lib/faithteams/api/v2/resource/contribution_type.rb +38 -0
  43. data/lib/faithteams/api/v2/resource/fund.rb +22 -0
  44. data/lib/faithteams/api/v2/resource/person.rb +48 -0
  45. data/lib/faithteams/api/v2/resource/user.rb +40 -0
  46. data/lib/faithteams/api/v2/resource.rb +18 -0
  47. data/lib/faithteams/api/v2.rb +15 -0
  48. data/lib/faithteams/api.rb +8 -0
  49. data/lib/faithteams/version.rb +6 -0
  50. data/lib/faithteams.rb +7 -0
  51. data/thunder-tests/.gitignore +2 -0
  52. data/thunder-tests/collections/tc_col_faithteams.json +2390 -0
  53. data/thunder-tests/environments/tc_env_faithteams.json +59 -0
  54. data/thunder-tests/faithteams.env.template +5 -0
  55. metadata +283 -0
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Entity
7
+ # Wraps a faithteams contribution object.
8
+ class Contribution < Base
9
+ # @return [Array<ContributionRecord>] the contribution records
10
+ def records
11
+ attributes.map do |record|
12
+ FaithTeams::API::V2::Entity::ContributionRecord.new(attributes: record)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Entity
7
+ # Wraps a faithteams contribution_record object.
8
+ class ContributionRecord < Base
9
+ # @return [Float, nil]
10
+ def amount
11
+ read_attribute(:amount)
12
+ end
13
+
14
+ # @return [Integer, nil]
15
+ def batch_id
16
+ read_attribute(:batchId)
17
+ end
18
+
19
+ # @return [String, nil]
20
+ def check_number
21
+ read_attribute(:checkNumber).presence
22
+ end
23
+
24
+ # @return [Integer, nil]
25
+ def contribution_id
26
+ read_attribute(:contributionId)
27
+ end
28
+
29
+ # @return [Integer, nil]
30
+ def contribution_type_id
31
+ read_attribute(:contributionTypeId)
32
+ end
33
+
34
+ # @return [String, nil]
35
+ def contribution_type_name
36
+ read_attribute(:contributionTypeName).presence
37
+ end
38
+
39
+ # @return [String, nil]
40
+ def created_datetime
41
+ read_attribute(:createdDtm).presence
42
+ end
43
+
44
+ # @return [Integer, nil]
45
+ def created_user_id
46
+ read_attribute(:createdUser)
47
+ end
48
+
49
+ # @return [Float, nil]
50
+ def fee
51
+ read_attribute(:fee)
52
+ end
53
+
54
+ # @return [Integer, nil]
55
+ def fund_id
56
+ read_attribute(:fundId)
57
+ end
58
+
59
+ # @return [String, nil]
60
+ def fund_name
61
+ read_attribute(:fundName).presence
62
+ end
63
+
64
+ # @return [String, nil]
65
+ def give_datetime
66
+ read_attribute(:giveDtm).presence
67
+ end
68
+
69
+ # @return [Float, nil]
70
+ def net_amount
71
+ read_attribute(:netAmount)
72
+ end
73
+
74
+ # @return [String, nil]
75
+ def note
76
+ read_attribute(:note).presence
77
+ end
78
+
79
+ # @return [Integer, nil]
80
+ def org_id
81
+ read_attribute(:orgId)
82
+ end
83
+
84
+ # @return [Integer, nil]
85
+ def parent_id
86
+ read_attribute(:parentId)
87
+ end
88
+
89
+ # @return [Integer, nil]
90
+ def person_id
91
+ read_attribute(:personId)
92
+ end
93
+
94
+ # @return [Integer, nil]
95
+ def person_id_2
96
+ read_attribute(:personId2)
97
+ end
98
+
99
+ # @return [String, nil] "H" for header, "D" for detail
100
+ def record_type
101
+ read_attribute(:recordType).presence
102
+ end
103
+
104
+ # @return [String, nil] "A" for active?
105
+ def status
106
+ read_attribute(:status).presence
107
+ end
108
+
109
+ # @return [Float, nil]
110
+ def total_amount
111
+ read_attribute(:totalAmount)
112
+ end
113
+
114
+ # @return [String, nil]
115
+ def updated_datetime
116
+ read_attribute(:updatedDtm).presence
117
+ end
118
+
119
+ # @return [Integer, nil]
120
+ def updated_user_id
121
+ read_attribute(:updatedUser)
122
+ end
123
+
124
+ # @return [Boolean]
125
+ def header?
126
+ record_type&.upcase == "H"
127
+ end
128
+
129
+ # @return [Boolean]
130
+ def detail?
131
+ record_type&.upcase == "D"
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Entity
7
+ # Wraps a faithteams contribution type object.
8
+ class ContributionType < Base
9
+ # @return [Integer, nil]
10
+ def id
11
+ read_attribute(:contributionTypeId)
12
+ end
13
+
14
+ # @return [String, nil]
15
+ def name
16
+ read_attribute(:name).presence
17
+ end
18
+
19
+ # @return [String, nil] "A" for active, "I" for inactive
20
+ def status
21
+ read_attribute(:status).presence
22
+ end
23
+
24
+ # @return [Boolean]
25
+ def tithely?
26
+ (name || "").strip.downcase == "tithely"
27
+ end
28
+
29
+ # @return [Boolean]
30
+ def active?
31
+ (status || "I").strip.upcase == "A"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Entity
7
+ # Wraps a faithteams fund object.
8
+ class Fund < Base
9
+ # @return [String, nil] "N" for no, "Y" for yes
10
+ def default
11
+ read_attribute(:isDefault).presence
12
+ end
13
+
14
+ # @return [String, nil]
15
+ def description
16
+ read_attribute(:description).presence
17
+ end
18
+
19
+ # @return [Integer, nil]
20
+ def fund_id
21
+ read_attribute(:fundId)
22
+ end
23
+
24
+ # @return [String, nil]
25
+ def name
26
+ read_attribute(:name).presence
27
+ end
28
+
29
+ # @return [String, nil] "A" for active, "I" for inactive
30
+ def online_status
31
+ read_attribute(:onlineStatus).presence
32
+ end
33
+
34
+ # @return [Integer, nil]
35
+ def org_id
36
+ read_attribute(:orgId)
37
+ end
38
+
39
+ # @return [String, nil] "A" for active, "I" for inactive
40
+ def status
41
+ read_attribute(:status).presence
42
+ end
43
+
44
+ # @return [String, nil] "T" for true?, "Y" for yes?
45
+ def tax_deductible
46
+ read_attribute(:taxDeductible).presence
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Entity
7
+ # Wraps an faithteams person object
8
+ class Person < Base
9
+ # @return [String, nil]
10
+ def email
11
+ read_attribute(:homeEmail).presence
12
+ end
13
+
14
+ # @return [String, nil]
15
+ def first_name
16
+ read_attribute(:firstName).presence
17
+ end
18
+
19
+ # @return [String, nil]
20
+ def home_address_city
21
+ read_attribute(:homeAddressCity).presence
22
+ end
23
+
24
+ # @return [String, nil]
25
+ def home_address_country
26
+ read_attribute(:homeAddressCountry).presence
27
+ end
28
+
29
+ # @return [String, nil]
30
+ def home_address_state
31
+ read_attribute(:homeAddressState).presence
32
+ end
33
+
34
+ # @return [String, nil]
35
+ def home_address_street_line1
36
+ read_attribute(:homeAddressStreetLine1).presence
37
+ end
38
+
39
+ # @return [String, nil]
40
+ def home_address_street_line2
41
+ read_attribute(:homeAddressStreetLine2).presence
42
+ end
43
+
44
+ # @return [String, nil]
45
+ def home_address_zip
46
+ read_attribute(:homeAddressZip).presence
47
+ end
48
+
49
+ # @return [String, nil]
50
+ def home_phone_number
51
+ read_attribute(:homePhoneNumber).presence
52
+ end
53
+
54
+ # @return [Integer, nil]
55
+ def id
56
+ read_attribute(:personId)
57
+ end
58
+
59
+ # @return [String, nil]
60
+ def last_name
61
+ read_attribute(:lastName).presence
62
+ end
63
+
64
+ # @return [Integer, nil]
65
+ def org_id
66
+ read_attribute(:orgId)
67
+ end
68
+
69
+ # @return [String, nil] "A" for active, "I" for inactive
70
+ def status
71
+ read_attribute(:status).presence
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "entity/base"
4
+ require_relative "entity/batch"
5
+ require_relative "entity/contribution"
6
+ require_relative "entity/contribution_record"
7
+ require_relative "entity/contribution_type"
8
+ require_relative "entity/fund"
9
+ require_relative "entity/person"
10
+
11
+ module FaithTeams
12
+ module API
13
+ module V2
14
+ module Entity; end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Error
7
+ # Thrown when a parameter is not given but should have been
8
+ class NoSearchParameterProvided < StandardError; end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Error
7
+ # A request failed to complete successfully.
8
+ class Request < StandardError
9
+ attr_reader :response
10
+
11
+ # Custom faithteams error about invalid API key
12
+ UNAUTHORIZED_ERROR_MESSAGE = "Unauthorized"
13
+
14
+ # Custom faithteams error when a resource is not found
15
+ NOT_FOUND_ERROR_MESSAGE = "Not Found"
16
+
17
+ # @param response [HTTP::Response]
18
+ # @param message [String]
19
+ def initialize(response:, message: "Request failed", skip_failure_message: false)
20
+ @response = response
21
+ message += ": #{failure_message}" unless failure_message.blank? || skip_failure_message
22
+ super(message)
23
+ end
24
+
25
+ # @return [String]
26
+ def failure_message
27
+ @failure_message ||= response.parse(:json).dig("message") rescue ""
28
+ rescue JSON::ParserError => e
29
+ e.capture
30
+ response.to_s
31
+ end
32
+
33
+ # @return [Boolean]
34
+ def unauthorized?
35
+ failure_message == UNAUTHORIZED_ERROR_MESSAGE
36
+ end
37
+
38
+ # @return [Boolean]
39
+ def not_found?
40
+ failure_message == NOT_FOUND_ERROR_MESSAGE
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "error/no_search_parameter_provided"
4
+ require_relative "error/request"
5
+
6
+ module FaithTeams
7
+ module API
8
+ module V2
9
+ # FaithTeams API error
10
+ module Error; end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "gateway_base"
4
+
5
+ module FaithTeams
6
+ module API
7
+ module V2
8
+ # Central gateway for all API resources
9
+ class Gateway < GatewayBase
10
+ # @param connection [FaithTeams::API::V2::Connection]
11
+ def initialize(connection:)
12
+ @connection = connection
13
+ end
14
+
15
+ # @return [Resource::Batch]
16
+ def batch
17
+ @batch ||= Resource::Batch.new(connection: connection)
18
+ end
19
+
20
+ # @return [Resource::Fund]
21
+ def fund
22
+ @fund ||= Resource::Fund.new(connection: connection)
23
+ end
24
+
25
+ # @return [Resource::Person]
26
+ def person
27
+ @person ||= Resource::Person.new(connection: connection)
28
+ end
29
+
30
+ # @return [Resource::Contribution]
31
+ def contribution
32
+ @contribution ||= Resource::Contribution.new(connection: connection)
33
+ end
34
+
35
+ # @return [Resource::User]
36
+ def user
37
+ @user ||= Resource::User.new(connection: connection)
38
+ end
39
+
40
+ # @return [Resource::ContributionType]
41
+ def contribution_type
42
+ @contribution_type ||= Resource::ContributionType.new(connection: connection)
43
+ end
44
+
45
+ def valid_connection?
46
+ connection.valid?
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ # A base class for all FaithTeam API versions
7
+ class GatewayBase
8
+ # @param connection [Integrations::API::Connection]
9
+ def initialize(connection:)
10
+ @connection = connection
11
+ end
12
+
13
+ # Required by integrations-gem
14
+ # @return [Boolean]
15
+ def valid_connection?
16
+ connection.valid?
17
+ end
18
+
19
+ protected
20
+
21
+ attr_reader :connection
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/keys"
4
+ require "active_support/core_ext/object/blank"
5
+
6
+ module FaithTeams
7
+ module API
8
+ module V2
9
+ module Resource
10
+ # Common Resource functionality
11
+ # Additional methods can be added but the following methods should not be missing
12
+ class Base < GatewayBase
13
+ # @param id [Integer] The contribution payment_id.
14
+ # @return [Entity::Base, nil]
15
+ def find(id:)
16
+ raise NotImplementedError
17
+ end
18
+
19
+ # @param args [Hash] Key values to search with
20
+ # @return [Array<Entity::Base>]
21
+ def search(**args)
22
+ raise NotImplementedError
23
+ end
24
+
25
+ # @param entity [Entity::Base]
26
+ # @return [Entity::Base, false]
27
+ def create(entity:)
28
+ raise NotImplementedError
29
+ end
30
+
31
+ # @param entity [Entity::Base]
32
+ # @return [Entity::Base, false]
33
+ def update(entity:)
34
+ raise NotImplementedError
35
+ end
36
+
37
+ # @param id [#to_s] ID of the entity to delete
38
+ # @return [Boolean]
39
+ def delete(id:)
40
+ raise NotImplementedError
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Resource
7
+ # Batch resource
8
+ class Batch < Base
9
+ # @param args [Hash] Keyword args
10
+ # @return [Array<Entity::Batch>]
11
+ def search(**args)
12
+ found = connection.get(path: "/batches", params: args)["data"]
13
+ return [] unless found.present?
14
+
15
+ found.map { |b| Entity::Batch.new(attributes: b) }
16
+ end
17
+
18
+ # @param id [Integer]
19
+ # @return [Entity::Batch, nil] containing all batch details
20
+ # @raise [Error::Request]
21
+ def find(id:)
22
+ raise FaithTeams::API::V2::Error::NoSearchParameterProvided if id.nil?
23
+
24
+ data = connection.get(path: "/batches/#{id}")["data"]
25
+ return nil unless data
26
+
27
+ Entity::Batch.new(attributes: data)
28
+ rescue Error::Request => e
29
+ return nil if e.response.code == 404
30
+ raise
31
+ end
32
+
33
+ # Searches for a batch by `dtm` and `title`
34
+ # @note The batches endpoint does not actually filter by title so we do the filtering here.
35
+ # @param batch [Entity::Batch]
36
+ # @return [Entity::Batch, nil]
37
+ def find_by_batch(batch:)
38
+ found = search(sort: "dtm", sortDirection: "desc", dtm: batch.created_datetime)
39
+ found.find { |b| !b.deleted? && b.title == batch.title }
40
+ end
41
+
42
+ # The response sends back the created batch in the `data` object.
43
+ # @param entity [Entity::Batch]
44
+ # @return [Entity::Batch]
45
+ # @raise [Error::Request]
46
+ def create(entity:)
47
+ data = connection.post(path: "/batches", body: entity.to_h)["data"]
48
+
49
+ Entity::Batch.new(attributes: data)
50
+ rescue Error::Request => e
51
+ raise Error::Request.new(response: e.response, message: "Request Unsuccessful: The batch #{entity.inspect} could not be created. FaithTeams API failure message: #{e.message}}") if e.response.status.success?
52
+ raise
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Resource
7
+ # A transaction in faithteams
8
+ class Contribution < Base
9
+ # @param entity [Entity::Contribution]
10
+ # @return [Entity::Contribution]
11
+ # @raise [Error::Request]
12
+ def create(entity:)
13
+ data = connection.post(path: "/contributions", body: entity.to_h)["data"]
14
+
15
+ Entity::Contribution.new(attributes: data)
16
+ rescue Error::Request => e
17
+ raise Error::Request.new(response: e.response, message: "Request Unsuccessful: The contribution #{entity.inspect} could not be created. FaithTeams API failure message: #{e.message}}") if e.response.status.success?
18
+ raise
19
+ end
20
+
21
+ # @param id [Integer] The contributions `parent_id`
22
+ # @return [Entity::Contribution, nil]
23
+ # @raise [Error::Request]
24
+ def find(id:)
25
+ raise FaithTeams::API::V2::Error::NoSearchParameterProvided if id.nil?
26
+
27
+ data = connection.get(path: "/contributions/#{id}")["data"]
28
+ return nil unless data.present?
29
+
30
+ Entity::Contribution.new(attributes: data)
31
+ rescue Error::Request => e
32
+ raise Error::Request.new(response: e.response, message: "Request Unsuccessful: The contribution with parent_id #{id} could not be found. FaithTeams API failure message: #{e.message}}") if e.response.status.success?
33
+ raise
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Resource
7
+ # The contribution type resource
8
+ class ContributionType < Base
9
+ # @param args [Hash] These are ignored as no filters are available for this endpoint
10
+ # @return [Entity::ContributionType]
11
+ def search(**args)
12
+ data = connection.get(path: "/contributiontypes", params: {}).fetch("data")
13
+
14
+ return nil unless data.present?
15
+
16
+ data.map do |record|
17
+ Entity::ContributionType.new(attributes: record)
18
+ end
19
+ end
20
+
21
+ # @param id [Integer]
22
+ # @return [Entity::ContributionType]
23
+ def find(id:)
24
+ return nil if id.blank?
25
+
26
+ data = connection.get(path: "/contributiontypes/#{id}", params: {}).fetch("data")
27
+
28
+ return nil unless data.present?
29
+
30
+ Entity::ContributionType.new(attributes: data)
31
+ rescue Error::Request => e
32
+ e.response.code == 404 ? nil : raise
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end