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
data/Gemfile.lock ADDED
@@ -0,0 +1,171 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ faithteams-api (2.0.1)
5
+ activesupport (>= 6.1.7)
6
+ http (~> 5.1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (7.1.3)
12
+ base64
13
+ bigdecimal
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ connection_pool (>= 2.2.5)
16
+ drb
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ mutex_m
20
+ tzinfo (~> 2.0)
21
+ addressable (2.8.6)
22
+ public_suffix (>= 2.0.2, < 6.0)
23
+ ast (2.4.2)
24
+ base64 (0.2.0)
25
+ bigdecimal (3.1.6)
26
+ byebug (11.1.3)
27
+ coderay (1.1.3)
28
+ concurrent-ruby (1.2.3)
29
+ connection_pool (2.4.1)
30
+ crack (0.4.6)
31
+ bigdecimal
32
+ rexml
33
+ diff-lcs (1.5.1)
34
+ docile (1.4.0)
35
+ domain_name (0.6.20240107)
36
+ drb (2.2.0)
37
+ ruby2_keywords
38
+ ffi (1.16.3)
39
+ ffi-compiler (1.0.1)
40
+ ffi (>= 1.0.0)
41
+ rake
42
+ formatador (1.1.0)
43
+ guard (2.18.1)
44
+ formatador (>= 0.2.4)
45
+ listen (>= 2.7, < 4.0)
46
+ lumberjack (>= 1.0.12, < 2.0)
47
+ nenv (~> 0.1)
48
+ notiffany (~> 0.0)
49
+ pry (>= 0.13.0)
50
+ shellany (~> 0.0)
51
+ thor (>= 0.18.1)
52
+ guard-compat (1.2.1)
53
+ guard-rspec (4.7.3)
54
+ guard (~> 2.1)
55
+ guard-compat (~> 1.1)
56
+ rspec (>= 2.99.0, < 4.0)
57
+ hashdiff (1.1.0)
58
+ http (5.2.0)
59
+ addressable (~> 2.8)
60
+ base64 (~> 0.1)
61
+ http-cookie (~> 1.0)
62
+ http-form_data (~> 2.2)
63
+ llhttp-ffi (~> 0.5.0)
64
+ http-cookie (1.0.5)
65
+ domain_name (~> 0.5)
66
+ http-form_data (2.3.0)
67
+ i18n (1.14.1)
68
+ concurrent-ruby (~> 1.0)
69
+ json (2.7.1)
70
+ language_server-protocol (3.17.0.3)
71
+ listen (3.8.0)
72
+ rb-fsevent (~> 0.10, >= 0.10.3)
73
+ rb-inotify (~> 0.9, >= 0.9.10)
74
+ llhttp-ffi (0.5.0)
75
+ ffi-compiler (~> 1.0)
76
+ rake (~> 13.0)
77
+ lumberjack (1.2.10)
78
+ method_source (1.0.0)
79
+ minitest (5.22.1)
80
+ mutex_m (0.2.0)
81
+ nenv (0.3.0)
82
+ notiffany (0.1.3)
83
+ nenv (~> 0.1)
84
+ shellany (~> 0.0)
85
+ parallel (1.24.0)
86
+ parser (3.3.0.5)
87
+ ast (~> 2.4.1)
88
+ racc
89
+ pry (0.14.2)
90
+ coderay (~> 1.1)
91
+ method_source (~> 1.0)
92
+ public_suffix (5.0.4)
93
+ racc (1.7.3)
94
+ rainbow (3.1.1)
95
+ rake (13.1.0)
96
+ rb-fsevent (0.11.2)
97
+ rb-inotify (0.10.1)
98
+ ffi (~> 1.0)
99
+ regexp_parser (2.9.0)
100
+ rexml (3.2.6)
101
+ rspec (3.13.0)
102
+ rspec-core (~> 3.13.0)
103
+ rspec-expectations (~> 3.13.0)
104
+ rspec-mocks (~> 3.13.0)
105
+ rspec-core (3.13.0)
106
+ rspec-support (~> 3.13.0)
107
+ rspec-expectations (3.13.0)
108
+ diff-lcs (>= 1.2.0, < 2.0)
109
+ rspec-support (~> 3.13.0)
110
+ rspec-mocks (3.13.0)
111
+ diff-lcs (>= 1.2.0, < 2.0)
112
+ rspec-support (~> 3.13.0)
113
+ rspec-support (3.13.0)
114
+ rubocop (1.60.2)
115
+ json (~> 2.3)
116
+ language_server-protocol (>= 3.17.0)
117
+ parallel (~> 1.10)
118
+ parser (>= 3.3.0.2)
119
+ rainbow (>= 2.2.2, < 4.0)
120
+ regexp_parser (>= 1.8, < 3.0)
121
+ rexml (>= 3.2.5, < 4.0)
122
+ rubocop-ast (>= 1.30.0, < 2.0)
123
+ ruby-progressbar (~> 1.7)
124
+ unicode-display_width (>= 2.4.0, < 3.0)
125
+ rubocop-ast (1.30.0)
126
+ parser (>= 3.2.1.0)
127
+ rubocop-performance (1.20.2)
128
+ rubocop (>= 1.48.1, < 2.0)
129
+ rubocop-ast (>= 1.30.0, < 2.0)
130
+ rubocop-rake (0.6.0)
131
+ rubocop (~> 1.0)
132
+ rubocop-rspec (1.42.0)
133
+ rubocop (>= 0.87.0)
134
+ ruby-progressbar (1.13.0)
135
+ ruby2_keywords (0.0.5)
136
+ shellany (0.0.1)
137
+ simplecov (0.22.0)
138
+ docile (~> 1.1)
139
+ simplecov-html (~> 0.11)
140
+ simplecov_json_formatter (~> 0.1)
141
+ simplecov-html (0.12.3)
142
+ simplecov_json_formatter (0.1.4)
143
+ thor (1.3.0)
144
+ tzinfo (2.0.6)
145
+ concurrent-ruby (~> 1.0)
146
+ unicode-display_width (2.5.0)
147
+ webmock (3.20.0)
148
+ addressable (>= 2.8.0)
149
+ crack (>= 0.3.2)
150
+ hashdiff (>= 0.4.0, < 2.0.0)
151
+ yard (0.9.34)
152
+
153
+ PLATFORMS
154
+ ruby
155
+
156
+ DEPENDENCIES
157
+ byebug (~> 11.1)
158
+ faithteams-api!
159
+ guard-rspec (~> 4.7)
160
+ rake (~> 13.0)
161
+ rspec (~> 3.12)
162
+ rubocop (~> 1.42)
163
+ rubocop-performance (~> 1.17)
164
+ rubocop-rake (~> 0.6)
165
+ rubocop-rspec (~> 1.42)
166
+ simplecov (~> 0.21)
167
+ webmock (~> 3.18)
168
+ yard (~> 0.9)
169
+
170
+ BUNDLED WITH
171
+ 2.4.13
data/Guardfile ADDED
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A sample Guardfile
4
+ # More info at https://github.com/guard/guard#readme
5
+
6
+ ## Uncomment and set this to only include directories you want to watch
7
+ # directories %w(app lib config test spec features) \
8
+ # .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
9
+
10
+ ## Note: if you are using the `directories` clause above and you are not
11
+ ## watching the project directory ('.'), then you will want to move
12
+ ## the Guardfile to a watched dir and symlink it back, e.g.
13
+ #
14
+ # $ mkdir config
15
+ # $ mv Guardfile config/
16
+ # $ ln -s config/Guardfile .
17
+ #
18
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
19
+
20
+ # Note: The cmd option is now required due to the increasing number of ways
21
+ # rspec may be run, below are examples of the most common uses.
22
+ # * bundler: 'bundle exec rspec'
23
+ # * bundler binstubs: 'bin/rspec'
24
+ # * spring: 'bin/rspec' (This will use spring if running and you have
25
+ # installed the spring binstubs per the docs)
26
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
27
+ # * 'just' rspec: 'rspec'
28
+
29
+ guard :rspec, cmd: "bundle exec rspec" do
30
+ require "guard/rspec/dsl"
31
+ dsl = Guard::RSpec::Dsl.new(self)
32
+
33
+ # Feel free to open issues for suggestions and improvements
34
+
35
+ # RSpec files
36
+ rspec = dsl.rspec
37
+ watch(rspec.spec_helper) { rspec.spec_dir }
38
+ watch(rspec.spec_support) { rspec.spec_dir }
39
+ watch(rspec.spec_files)
40
+
41
+ # Ruby files
42
+ ruby = dsl.ruby
43
+ dsl.watch_spec_files_for(ruby.lib_files)
44
+
45
+ # Rails files
46
+ rails = dsl.rails(view_extensions: %w(erb haml slim))
47
+
48
+ # Rails config changes
49
+ watch(rails.spec_helper) { rspec.spec_dir }
50
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Tithe.ly
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # FaithTeams API
2
+ FaithTeams API client gem for use with FaithTeams API. See [FaithTeams API Documentation](https://api.faithteams.com/docs) for more information.
3
+
4
+ ## Overview and Purpose
5
+ It provides a wrapper around the FaithTeams API and includes the following collection of classes and methods for each API version that can be used to interact with the FaithTeams API:
6
+
7
+ * `FaithTeams::API::V*::Connection` - Takes FaithTeams credentials (`user_id` and `password`) and is responsible for:
8
+ * establishing and validating a connection to the FaithTeams API
9
+ * providing the underlying methods used by the various API resources to make specific API calls.
10
+ * handling request errors.
11
+ * `FaithTeams::API::V*::Gateway` - Takes a `FaithTeams::Connection` and is responsible for providing a collection of API resources.
12
+ * `FaithTeams::API::V*::Resource` - Provides CRUD functionality for each resource.
13
+ * `FaithTeams::API::V*::Error::*` - All necessary errors.
14
+ * `FaithTeams::API::V*::Entity::*` - All necessary entities.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem "faithteams"
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ `bundle install`
27
+
28
+ Or install it yourself as:
29
+
30
+ `gem install faithteams`
31
+
32
+ ## Contributing
33
+
34
+ ### How to Contribute
35
+
36
+ 1. Adhere to the [Code of Conduct](./CODE_OF_CONDUCT.md)
37
+ 1. Fork the project.
38
+ 1. Create a new branch for your feature: `git checkout -b feature-name`.
39
+ 1. Commit your changes: `git commit -m 'Add new feature'`. Please reference a GitHub issue if applicable. See [linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue). Please be sure to include an appropriate entry in the [CHANGELOG.md](./CHANGELOG.md).
40
+ 1. Push to your branch: `git push origin feature-name`.
41
+ 1. Open a pull request. Please add information about why this is necessary, citing specific examples if possible.
42
+
43
+ ### Code of Conduct
44
+
45
+ This project has a [Code of Conduct](./CODE_OF_CONDUCT.md). Please read through this document and ensure compliance before contributing.
46
+
47
+ ### Contributor Guidelines
48
+
49
+ Contributions should adhere to the [API Client Gateway Resource Interface](./guides/api_client_interface.md). Additional API endpoints should be added to the Thunder Client Collection with appropriate tests included.
50
+
51
+ ## Testing
52
+
53
+ To run the tests in the gem: `bundle exec rspec`
54
+
55
+ To run a specific test, use a pattern: `bundle exec rspec -P "**/contribution_spec.rb"`
56
+
57
+ Use the Thunder Client extension for VS Code to test/inspect API calls.
58
+
59
+ ## Gem Publishing
60
+
61
+ General instructions for publishing a gem are available in this [RubyGems guide](https://guides.rubygems.org/publishing/#publishing-to-rubygemsorg).
62
+
63
+ 1. Make sure you have a [RubyGems account](https://rubygems.org/sign_in).
64
+ 1. Ensure the gem can be built and is at the correct version number: `bundle exec rake install`
65
+ 1. Publish the gem `gem push pkg/faithteams-api-2.0.0.gem
66
+
67
+ ## License
68
+
69
+ This project is licensed under the [MIT License](./LICENSE).
70
+
71
+ ## Contact and Bug Reports
72
+
73
+ You can contact the project maintainers or file a bug report through GitHub Issues on this repository. Please provide complete details so that your question or issue may be resolved as soon as possible.
74
+
75
+ [comment]: <> (TODO: Add FaithTeams contact information)
76
+
77
+ ## Project Status
78
+
79
+ This project is being actively maintained and is stable for production use.
80
+
81
+ ## Tithe.ly
82
+
83
+ ![Tithe.ly Logo](https://assets-global.website-files.com/5f6a31379c9e2712518b8d6c/61fbe41d8e639d18d7c516b7_Logomark.svg)
84
+
85
+ With tools like text and email messaging, custom church apps and websites, church management software, and digital giving, [Tithe.ly](https://tithe.ly/) provides the tools you need to engage with your church online, stay connected, increase generosity, and simplify the lives of your staff.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "faithteams"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/faithteams/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "faithteams-api"
7
+ spec.version = FaithTeams::VERSION
8
+ spec.authors = ["Tithe.ly Integrations"]
9
+ spec.email = ["integrations@tithe.ly"]
10
+
11
+ spec.summary = "A Faithteams API client gem."
12
+ spec.description = "Provides methods and utilities for interacting with the faithteams API."
13
+ spec.homepage = "https://github.com/tithely/faithteams-api"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
16
+
17
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = "https://github.com/tithely/faithteams-api"
21
+ spec.metadata["changelog_uri"] = "https://github.com/tithely/faithteams-api/blob/master/doc/CHANGELOG.md"
22
+ spec.metadata["github_repo"] = "https://github.com/tithely/faithteams-api"
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
+ spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
27
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ spec.add_dependency "activesupport", ">= 6.1.7"
34
+ spec.add_dependency "http", "~> 5.1"
35
+
36
+ spec.add_development_dependency "byebug", "~> 11.1"
37
+ spec.add_development_dependency "guard-rspec", "~> 4.7"
38
+ spec.add_development_dependency "simplecov", "~> 0.21"
39
+ spec.add_development_dependency "rake", "~> 13.0"
40
+ spec.add_development_dependency "rspec", "~> 3.12"
41
+ spec.add_development_dependency "rubocop", "~> 1.42"
42
+ spec.add_development_dependency "rubocop-performance", "~> 1.17"
43
+ spec.add_development_dependency "rubocop-rake", "~> 0.6"
44
+ spec.add_development_dependency "rubocop-rspec", "~> 1.42"
45
+ spec.add_development_dependency "webmock", "~> 3.18"
46
+ spec.add_development_dependency "yard", "~> 0.9"
47
+ end
@@ -0,0 +1,18 @@
1
+ # API Client Interface (ACI)
2
+
3
+ The ACI should provide at minimum the following functions in its Gateway to allow interaction with the client API in a standard way. These resources should descend from a common base that provides authentication and a request mechanism (via HTTP gem).
4
+ - batch
5
+ - contribution
6
+ - contribution_type
7
+ - fund
8
+ - person
9
+
10
+ The methods above return an object that should have the following methods:
11
+ - **find(id:)** - Finds a single record by id. Returns an entity or nil.
12
+ - **search(\*\*args)** - Potentially returns multiple records given various parameters. Returns an array of entities or empty array.
13
+ - **create(entity:)** - Create a new record. Returns entity or nil on failure.
14
+ - **update(entity:)** - Update an existing record. Returns boolean.
15
+ - **delete(id:)** - Remove an existing record. Returns boolean.
16
+ - **<nested_resource>(resource_id:)** - This is another resource which is nested under the current resource (e.g. /people/:person_id/emails/:email_id). The nested resource would be the same as if the it was at the top level in the Gateway. We would then call it with something like this to find emails on a specific person:
17
+ gateway.person.email(person_id: <id>).search(<param>: <param-value>)
18
+ Any method can raise an exception on failure.
@@ -0,0 +1,11 @@
1
+ # Release Process
2
+
3
+ 1. Branch off of the commit you want to release (`git checkout -b x.x.x`).
4
+ 1. Update the changelog version information and make sure that all changes to be released have been documented.
5
+ 1. Bump the version number in `lib/faithteams/version.rb` to the version to be released.
6
+ 1. Create a PR, look for approvals and merge this in to master.
7
+ 1. Tag master at the new commit with the version number (`git tag -a x.x.x`).
8
+ 1. Push this tag up to origin `git push origin x.x.x`.
9
+ 1. Head over to GitHub to create a [new release](https://github.com/tithely/faithteams-api/releases/new). Make sure to select the tag that you just pushed, place the version number as the release name and copy in the associated changelog contents into the description. Publish this release.
10
+ 1. This will kick off a deploy action which you can watch [here](https://github.com/tithely/faithteams-api/actions?query=workflow%3A%22Ruby+Gem%22).
11
+ 1. Once the action completes, verify the new version of the package is available [here](https://github.com/tithely/faithteams-api/packages).
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+ require_relative "error"
5
+
6
+ module FaithTeams
7
+ module API
8
+ module V2
9
+ # Faithteams API v2 connection
10
+ class Connection
11
+ # Specific base urls for different resources
12
+ ENDPOINT_BASE_URLS = {
13
+ "authenticate" => "https://app.faithteams.com/api/v2",
14
+ "batches" => "https://api-v2.faithteams.com",
15
+ "contributions" => "https://api-v2.faithteams.com",
16
+ "contributiontypes" => "https://api-v2.faithteams.com",
17
+ "funds" => "https://api-v2.faithteams.com",
18
+ "people" => "https://app.faithteams.com/api/v2"
19
+ }
20
+
21
+ attr_reader :user_id, :password
22
+
23
+ # @param user_id [String]
24
+ # @param password [String]
25
+ def initialize(user_id:, password:)
26
+ raise ArgumentError.new("A user_id is required") if user_id.blank?
27
+ raise ArgumentError.new("A password is required") if password.blank?
28
+
29
+ @user_id = user_id
30
+ @password = password
31
+ end
32
+
33
+ # Is the connection to FaithTeams valid?
34
+ # @return [Boolean]
35
+ def valid?
36
+ get(path: "/contributiontypes")
37
+ true
38
+ rescue Error::Request
39
+ false
40
+ end
41
+
42
+ # @param path [String]
43
+ # @param params [Hash] Parameters to send with the request
44
+ # @return [Hash]
45
+ # @raise [Error::Request]
46
+ def get(path:, params: {})
47
+ request_and_parse(method: :get, path: path, params: params)
48
+ end
49
+
50
+ # @param path [String]
51
+ # @param body [Hash, nil] Body to send
52
+ # @return [Hash]
53
+ # @raise [Error::Request]
54
+ def post(path:, body: nil)
55
+ request_and_parse(method: :post, path: path, body: body)
56
+ end
57
+
58
+ # Request an endpoint from faithteams, checking for errors
59
+ # @param method [String] :get or :post
60
+ # @param path [String] Path to the endpoint relative to ENDPOINT_BASE_URLS
61
+ # @param params [Hash] Request parameters
62
+ # @param body [Hash] Body to send
63
+ # @return [HTTP::Response] Results of the request
64
+ # @raise [Error::Request] Caller is responsible for capturing the error if needed
65
+ def request(method: :get, path:, params: {}, body: {})
66
+ url = "#{base_url(path: path)}#{path}"
67
+
68
+ retries ||= 0
69
+ response = nil
70
+ loop do
71
+ retries += 1
72
+
73
+ case method.to_s
74
+ when "post"
75
+ response = http.post(url, json: body)
76
+ else # get
77
+ response = http.get(url, params: params)
78
+ end
79
+ break if response.status != 401 || retries >= 2
80
+
81
+ authenticate
82
+ end
83
+
84
+ raise Error::Request.new(response: response, message: "Request unsuccessful (#{response.status})") unless response.status.success?
85
+
86
+ response
87
+ end
88
+
89
+ # Request an endpoint from faithteams and parse the response
90
+ # @param method [String] :get or :post
91
+ # @param path [String] Path to the endpoint relative to ENDPOINT_BASE_URLS
92
+ # @param params [Hash] Request parameters
93
+ # @param body [Hash] Body to send
94
+ # @return [Hash] Contents of the body
95
+ # @raise [Error::Request] Caller is responsible for capturing the error if needed
96
+ def request_and_parse(method: "get", path:, params: {}, body: {})
97
+ response = request(method: method, path: path, params: params, body: body)
98
+ begin
99
+ response_body = response.parse(:json)
100
+ rescue JSON::ParserError
101
+ raise Error::Request.new(response: response, message: "Failed to parse JSON")
102
+ end
103
+
104
+ # raise errors when "status" = 200 but "success" = false
105
+ raise Error::Request.new(response: response, message: "Request unsuccessful") unless response_body["success"] == true
106
+
107
+ response_body
108
+ end
109
+
110
+ # @return [Resource::User]
111
+ def user_resource
112
+ @user_resource ||= Resource::User.new(connection: self)
113
+ end
114
+
115
+ private
116
+
117
+ # @return [HTTP::Client]
118
+ def http
119
+ @http ||= HTTP.headers("Token" => "#{auth_token}")
120
+ end
121
+
122
+ # @param path [String]
123
+ # @return [String]
124
+ def base_url(path:)
125
+ ENDPOINT_BASE_URLS[path.split("/")[1]]
126
+ end
127
+
128
+ # Set the auth_token for these requests
129
+ # @return [String]
130
+ def auth_token
131
+ @auth_token ||= user_resource.authenticate
132
+ end
133
+
134
+ # Resets existing auth_token and re-authenticates
135
+ def authenticate
136
+ @auth_token = nil
137
+ auth_token
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ # Wraps entities returned from the faithteams api.
7
+ module Entity
8
+ # Common entity functionality
9
+ class Base
10
+ # New instance of the class.
11
+ def initialize(attributes:)
12
+ @attributes = attributes
13
+ end
14
+
15
+ # @return [Hash]
16
+ def to_h
17
+ attributes
18
+ end
19
+
20
+ # @return [Boolean]
21
+ def saved?
22
+ !!read_attribute(:id)
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :attributes
28
+
29
+ def read_attribute(attribute)
30
+ attributes[attribute.to_s]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaithTeams
4
+ module API
5
+ module V2
6
+ module Entity
7
+ # Wraps an faithteams batch object
8
+ class Batch < Base
9
+ # @return [Integer, nil]
10
+ def batch_id
11
+ read_attribute(:batchId)
12
+ end
13
+ alias_method :id, :batch_id
14
+
15
+ # @return [Array<FaithTeams::API::V2::Entity::Contributions>]
16
+ def contributions
17
+ records = read_attribute(:contributions)
18
+ return [] unless records.present?
19
+
20
+ records.group_by { |r| r["parentId"] }
21
+ .values
22
+ .map { FaithTeams::API::V2::Entity::Contribution.new(attributes: _1) }
23
+ end
24
+
25
+ # @return [String, nil]
26
+ def created_datetime
27
+ read_attribute(:dtm).presence
28
+ end
29
+
30
+ # @return [Integer, nil]
31
+ def org_id
32
+ read_attribute(:orgId)
33
+ end
34
+
35
+ # @return [String, nil] "O" for open, "C" for closed, "D" for deleted
36
+ def status
37
+ read_attribute(:status).presence
38
+ end
39
+
40
+ # @return [Boolean]
41
+ def open?
42
+ status == "O"
43
+ end
44
+
45
+ # @return [Boolean]
46
+ def deleted?
47
+ status == "D"
48
+ end
49
+
50
+ # @return [String, nil]
51
+ def title
52
+ read_attribute(:title).presence
53
+ end
54
+
55
+ # @return [String, nil]
56
+ def updated_datetime
57
+ read_attribute(:updatedDtm).presence
58
+ end
59
+
60
+ # @return [Integer, nil]
61
+ def updated_user_id
62
+ read_attribute(:updatedUser)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end