fellowshipone-api 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +64 -0
- data/README.rdoc +44 -0
- data/Rakefile +32 -0
- data/fellowshipone_api.gemspec +25 -0
- data/lib/api/api_object.rb +141 -0
- data/lib/api/communication.rb +59 -0
- data/lib/api/contribution.rb +97 -0
- data/lib/api/contribution_list.rb +57 -0
- data/lib/api/fund.rb +40 -0
- data/lib/api/fund_list.rb +53 -0
- data/lib/api/household.rb +50 -0
- data/lib/api/household_list.rb +78 -0
- data/lib/api/member_household_list.rb +73 -0
- data/lib/api/mergeable_household_list.rb +79 -0
- data/lib/api/mergeable_person_list.rb +110 -0
- data/lib/api/person.rb +169 -0
- data/lib/api/person_list.rb +85 -0
- data/lib/api/search.rb +55 -0
- data/lib/auto_load.rb +17 -0
- data/lib/common.rb +76 -0
- data/lib/exceptions.rb +5 -0
- data/lib/fellowship_one.rb +54 -0
- data/lib/oauth_monkey_patch.rb +13 -0
- data/lib/readers/api_reader.rb +34 -0
- data/lib/readers/communication_reader.rb +19 -0
- data/lib/readers/contribution_list_reader.rb +37 -0
- data/lib/readers/contribution_reader.rb +18 -0
- data/lib/readers/fund_list_reader.rb +13 -0
- data/lib/readers/fund_reader.rb +14 -0
- data/lib/readers/household_list_reader.rb +62 -0
- data/lib/readers/household_reader.rb +18 -0
- data/lib/readers/member_household_list_reader.rb +27 -0
- data/lib/readers/person_list_reader.rb +37 -0
- data/lib/readers/person_reader.rb +20 -0
- data/lib/writers/api_writer.rb +64 -0
- data/lib/writers/communication_writer.rb +27 -0
- data/lib/writers/contribution_writer.rb +28 -0
- data/lib/writers/household_writer.rb +30 -0
- data/lib/writers/person_writer.rb +64 -0
- data/spec/api/person_spec.rb +21 -0
- data/spec/functional/fellowship_one_spec.rb +17 -0
- data/spec/readers/api_reader_spec.rb +7 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/vcr_setup.rb +5 -0
- data/spec/writers/api_writer_spec.rb +7 -0
- metadata +129 -0
data/lib/api/person.rb
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
module FellowshipOne
|
2
|
+
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
PersonAddress = Struct.new(:is_primary?, :street, :street2, :city, :state, :postal_code)
|
6
|
+
PersonCommunication = Struct.new(:is_phone?, :is_mobile?, :is_email?, :type, :value, :preferred?)
|
7
|
+
|
8
|
+
class Person < ApiObject
|
9
|
+
attr_accessor :addresses,
|
10
|
+
:communications
|
11
|
+
|
12
|
+
f1_attr_accessor :id,
|
13
|
+
:uri,
|
14
|
+
:image_uri,
|
15
|
+
:old_id,
|
16
|
+
:i_code,
|
17
|
+
:household_id,
|
18
|
+
:old_household_id,
|
19
|
+
:title,
|
20
|
+
:salutation,
|
21
|
+
:prefix,
|
22
|
+
:first_name,
|
23
|
+
:last_name,
|
24
|
+
:suffix,
|
25
|
+
:middle_name,
|
26
|
+
:goes_by_name,
|
27
|
+
:former_name,
|
28
|
+
:gender,
|
29
|
+
:date_of_birth,
|
30
|
+
:marital_status,
|
31
|
+
:household_member_type,
|
32
|
+
:is_authorized,
|
33
|
+
:status,
|
34
|
+
:occupation,
|
35
|
+
:employer,
|
36
|
+
:school,
|
37
|
+
:denomination,
|
38
|
+
:former_church,
|
39
|
+
:bar_code,
|
40
|
+
:member_envelope_code,
|
41
|
+
:default_tag_comment,
|
42
|
+
:weblink,
|
43
|
+
:solicit,
|
44
|
+
:thank,
|
45
|
+
:first_record,
|
46
|
+
:last_match_date,
|
47
|
+
:created_date,
|
48
|
+
:last_updated_date
|
49
|
+
|
50
|
+
# Loads the user by the specified ID.
|
51
|
+
#
|
52
|
+
# @param person_id The ID of the person to load.
|
53
|
+
#
|
54
|
+
# Returns a new Person object.
|
55
|
+
def self.load_by_id(person_id)
|
56
|
+
reader = PersonReader.new(person_id)
|
57
|
+
self.new(reader)
|
58
|
+
rescue
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# Constructor.
|
64
|
+
#
|
65
|
+
# @param reader (optional) The object that has the data. This can be a PersonReader or Hash object.
|
66
|
+
# @param options (optional) Options for including more information.
|
67
|
+
def initialize(reader = nil, options = {})
|
68
|
+
@writer_object = PersonWriter
|
69
|
+
if reader.is_a?(PersonReader)
|
70
|
+
initialize_from_json_object(reader.load_feed['person'])
|
71
|
+
elsif reader.is_a?(Hash)
|
72
|
+
initialize_from_json_object(reader)
|
73
|
+
else # new empty
|
74
|
+
reader = PersonReader.new
|
75
|
+
initialize_from_json_object(reader.load_new['person'])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def is_head_of_household?
|
81
|
+
(!self.household_member_type.nil? and self.household_member_type['name'].downcase == 'head')
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def family_role
|
86
|
+
begin
|
87
|
+
self.household_member_type['name']
|
88
|
+
rescue
|
89
|
+
'Other'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
def is_child?
|
95
|
+
begin
|
96
|
+
self.household_member_type['name'].downcase == 'child'
|
97
|
+
rescue
|
98
|
+
false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def addresses
|
104
|
+
return nil if @addresses.nil?
|
105
|
+
return @addresses_cache unless @addresses_cache.nil?
|
106
|
+
|
107
|
+
@addresses_cache = []
|
108
|
+
@addresses['address'].each do |addr|
|
109
|
+
@addresses_cache << PersonAddress.new(
|
110
|
+
addr['addressType']['name'].downcase == 'primary',
|
111
|
+
addr['address1'],
|
112
|
+
addr['address2'],
|
113
|
+
addr['city'],
|
114
|
+
addr['stProvince'],
|
115
|
+
addr['postalCode']
|
116
|
+
)
|
117
|
+
end
|
118
|
+
@addresses_cache
|
119
|
+
end
|
120
|
+
|
121
|
+
def email_addresses
|
122
|
+
self.communications.collect { |c| c[:is_email?] ? c[:value] : nil }.compact
|
123
|
+
end
|
124
|
+
|
125
|
+
def all_numbers
|
126
|
+
self.communications.collect { |c| (c[:is_phone?] or c[:is_mobile?]) ? c[:value] : nil }.compact
|
127
|
+
end
|
128
|
+
|
129
|
+
def phone_numbers
|
130
|
+
self.communications.collect { |c| c[:is_phone?] ? c[:value] : nil }.compact
|
131
|
+
end
|
132
|
+
|
133
|
+
def mobile_numbers
|
134
|
+
self.communications.collect { |c| c[:is_mobile?] ? c[:value] : nil }.compact
|
135
|
+
end
|
136
|
+
|
137
|
+
def communications
|
138
|
+
return nil if @communications.nil?
|
139
|
+
return @communications_cache unless @communications_cache.nil?
|
140
|
+
|
141
|
+
@communications_cache = []
|
142
|
+
@communications['communication'].each do |comm|
|
143
|
+
@communications_cache << PersonCommunication.new(
|
144
|
+
comm['communicationType']['name'].to_s.downcase.include?('phone'),
|
145
|
+
comm['communicationType']['name'].to_s.downcase.include?('mobile'),
|
146
|
+
comm['communicationType']['name'].to_s.downcase.include?('email'),
|
147
|
+
comm['communicationType']['name'],
|
148
|
+
comm['communicationValue'],
|
149
|
+
comm['preferred'].to_s.downcase == 'true'
|
150
|
+
)
|
151
|
+
end
|
152
|
+
@communications_cache
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
def _field_map
|
157
|
+
{:id => '@id',
|
158
|
+
:uri => '@uri',
|
159
|
+
:imageUri => '@imageURI',
|
160
|
+
:oldId => '@oldID',
|
161
|
+
:iCode => '@iCode',
|
162
|
+
:householdId => '@householdID',
|
163
|
+
:oldHouseholdId => '@oldHouseholdID'}
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module FellowshipOne
|
2
|
+
|
3
|
+
class PersonList
|
4
|
+
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_reader :count, :page_number, :total_records, :additional_pages
|
8
|
+
|
9
|
+
|
10
|
+
# Constructor.
|
11
|
+
#
|
12
|
+
# @param options A hash of options for loading the list.
|
13
|
+
#
|
14
|
+
# Options:
|
15
|
+
# :page - (optional) The page number to get.
|
16
|
+
# :reader - (optional) The Reader to use to load the data.
|
17
|
+
def initialize(options)
|
18
|
+
#options[:page] ||= 1
|
19
|
+
reader = options[:reader] || FellowshipOne::PersonListReader.new(options)
|
20
|
+
@json_data = reader.load_feed
|
21
|
+
|
22
|
+
@count = @json_data['@count'].to_i
|
23
|
+
@page_number = @json_data['@pageNumber'].to_i
|
24
|
+
@total_records = @json_data['@totalRecords'].to_i
|
25
|
+
@additional_pages = @json_data['@additionalPages'].to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# All the people in the list.
|
30
|
+
#
|
31
|
+
# @return array of names (first last).
|
32
|
+
def all_names
|
33
|
+
return [] unless @json_data['person']
|
34
|
+
@json_data['person'].collect { |person| [person['firstName'], person['lastName']].join(' ') }
|
35
|
+
end
|
36
|
+
|
37
|
+
alias_method :names, :all_names
|
38
|
+
|
39
|
+
|
40
|
+
# Get the specified person.
|
41
|
+
#
|
42
|
+
# @param index The index of the person to get.
|
43
|
+
#
|
44
|
+
# @return [Person]
|
45
|
+
def [](index)
|
46
|
+
Person.new( @json_data['person'][index] ) if @json_data['person'] and @json_data['person'][index]
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# This method is needed for Enumerable.
|
51
|
+
def each &block
|
52
|
+
@json_data['person'].each{ |person| yield( Person.new(person) )}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Alias the count method
|
56
|
+
alias :size :count
|
57
|
+
|
58
|
+
# Checks if the list is empty.
|
59
|
+
#
|
60
|
+
# @return True on empty, false otherwise.
|
61
|
+
def empty?
|
62
|
+
#@json_data['person'].empty?
|
63
|
+
self.count == 0 ? true : false
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Get all the people ids in the list.
|
68
|
+
#
|
69
|
+
# @return An array of people ids.
|
70
|
+
def ids
|
71
|
+
(@json_data['person'].collect { |person| person['@id'] }).uniq
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# Access to the raw JSON data. This method is needed for merging lists.
|
76
|
+
#
|
77
|
+
# @returns Raw JSON data.
|
78
|
+
def raw_data
|
79
|
+
@json_data
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
end
|
data/lib/api/search.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module FellowshipOne
|
2
|
+
|
3
|
+
class Search
|
4
|
+
|
5
|
+
def self.search_for_contributions_by_date(start_date, end_date, page=1, per_page=500)
|
6
|
+
options = {:start_date => start_date, :end_date => end_date, :page => page, :per_page => per_page}
|
7
|
+
reader = FellowshipOne::ContributionListReader.new(options)
|
8
|
+
ContributionList.new({:reader => reader})
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.search_for_contributions_by_household_id(household_id, page=1, per_page=500)
|
12
|
+
options = {:household_id => household_id, :page => page, :per_page => per_page}
|
13
|
+
reader = FellowshipOne::ContributionListReader.new(options)
|
14
|
+
ContributionList.new({:reader => reader})
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.search_for_contributions_by_individual_id(individual_id, page=1, per_page=500)
|
18
|
+
options = {:individual_id => individual_id, :page => page, :per_page => per_page}
|
19
|
+
reader = FellowshipOne::ContributionListReader.new(options)
|
20
|
+
ContributionList.new({:reader => reader})
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.search_for_person_by_name(query, page=1)
|
24
|
+
options = {:page => page, :search_for => query}
|
25
|
+
reader = FellowshipOne::PersonListReader.new(options)
|
26
|
+
PersonList.new({:reader => reader})
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.search_for_person_by_household_id(query, page=1)
|
30
|
+
options = {:page => page, :hsdid => query}
|
31
|
+
reader = FellowshipOne::PersonListReader.new(options)
|
32
|
+
PersonList.new({:reader => reader})
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.search_for_person_by_communication(query, page=1)
|
36
|
+
options = {:page => page, :communication => query}
|
37
|
+
reader = FellowshipOne::PersonListReader.new(options)
|
38
|
+
PersonList.new({:reader => reader})
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.search_for_person_created_on_or_after(created_date, page=1)
|
42
|
+
options = {:page => page, :created_date => created_date}
|
43
|
+
reader = FellowshipOne::PersonListReader.new(options)
|
44
|
+
PersonList.new({:reader => reader})
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.search_for_household_by_name(name, page=1)
|
48
|
+
options = {:page => page, :search_for => name}
|
49
|
+
reader = FellowshipOne::HouseholdListReader.new(options)
|
50
|
+
HouseholdList.new({:reader => reader})
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/lib/auto_load.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module FellowshipOne
|
2
|
+
|
3
|
+
require FELLOWSHIPONE_LIB_DIR + '/exceptions.rb'
|
4
|
+
|
5
|
+
api_path = FELLOWSHIPONE_LIB_DIR + '/api/'
|
6
|
+
require api_path + 'api_object.rb'
|
7
|
+
Dir["#{api_path}/*.rb"].each { |f| require(f) }
|
8
|
+
|
9
|
+
readers_path = FELLOWSHIPONE_LIB_DIR + '/readers/'
|
10
|
+
require readers_path + 'api_reader.rb'
|
11
|
+
Dir["#{readers_path}/*.rb"].each { |f| require(f) }
|
12
|
+
|
13
|
+
writers_path = FELLOWSHIPONE_LIB_DIR + '/writers/'
|
14
|
+
require writers_path + 'api_writer.rb'
|
15
|
+
Dir["#{writers_path}/*.rb"].each { |f| require(f) }
|
16
|
+
|
17
|
+
end
|
data/lib/common.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
module FellowshipOne
|
2
|
+
require 'json'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
def self.api_request(method, path, params = {}, body = '')
|
6
|
+
# response = case method
|
7
|
+
# when :post
|
8
|
+
# Typhoeus::Request.post(url, {:headers => self._build_api_headers, :body => body})
|
9
|
+
# when :get
|
10
|
+
# Typhoeus::Request.get(url, {:headers => self._build_api_headers, :params => params})
|
11
|
+
# when :put
|
12
|
+
# Typhoeus::Request.put(url, {:headers => self._build_api_headers, :body => body})
|
13
|
+
# when :delete
|
14
|
+
# Typhoeus::Request.delete(url, {:headers => self._build_api_headers, :params => params})
|
15
|
+
# end
|
16
|
+
|
17
|
+
response = self._oauth_request_get(method, path, params, body)
|
18
|
+
|
19
|
+
unless response.success?
|
20
|
+
puts response.inspect
|
21
|
+
if response.code > 0
|
22
|
+
raise FellowshipOneExceptions::UnableToConnectToFellowshipOne.new(response.body)
|
23
|
+
else
|
24
|
+
begin
|
25
|
+
error_messages = JSON.parse(response.body)['error_message']
|
26
|
+
rescue
|
27
|
+
response_code_desc = response.headers.partition("\r\n")[0].sub(/^\S+/, '') rescue nil
|
28
|
+
raise FellowshipOneExceptions::UnknownErrorConnectingToFellowshipOne.new("Unknown error when connecting to FellowshipOne API. #{response_code_desc}")
|
29
|
+
else
|
30
|
+
raise FellowshipOneExceptions::FellowshipOneResponseError.new(error_messages)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
response
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def self._oauth_request_get(method, path, params, body)
|
40
|
+
consumer_env = FellowshipOne::Api.is_production ? '' : '.staging'
|
41
|
+
base_url = "https://#{FellowshipOne::Api.church_code}#{consumer_env}.fellowshiponeapi.com"
|
42
|
+
url = base_url + path
|
43
|
+
if method == :get
|
44
|
+
url_params = params.collect { |k, v| "#{k}=#{CGI::escape(v.to_s)}" }.join('&')
|
45
|
+
url_params = nil if url_params.empty?
|
46
|
+
url = [url, url_params].compact.join('?')
|
47
|
+
params = {}
|
48
|
+
end
|
49
|
+
|
50
|
+
consumer = OAuth::Consumer.new(FellowshipOne::Api.consumer_key,
|
51
|
+
FellowshipOne::Api.consumer_secret,
|
52
|
+
:site => base_url,
|
53
|
+
:http_method => method)
|
54
|
+
access_token = OAuth::AccessToken.new(consumer, FellowshipOne::Api.api_token, FellowshipOne::Api.api_secret)
|
55
|
+
|
56
|
+
options = {:params => params, :method => method, :body => body}
|
57
|
+
oauth_params = {:consumer => consumer, :token => access_token}
|
58
|
+
hydra = Typhoeus::Hydra.new
|
59
|
+
req = Typhoeus::Request.new(url, options)
|
60
|
+
|
61
|
+
# {'Content-Type' => 'application/vnd.fellowshiponeapi.com.people.people.v2+json'}
|
62
|
+
# req.headers.merge!({'Content-Type' => 'application/json'})
|
63
|
+
req.options[:headers].merge!({'Content-Type' => 'application/json'})
|
64
|
+
oauth_helper = OAuth::Client::Helper.new(req, oauth_params.merge(:request_uri => url))
|
65
|
+
|
66
|
+
#req.headers.merge!({"Authorization" => oauth_helper.header})
|
67
|
+
req.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
|
68
|
+
|
69
|
+
hydra.queue(req)
|
70
|
+
hydra.run
|
71
|
+
|
72
|
+
req.response
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
data/lib/exceptions.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'oauth'
|
2
|
+
require 'yaml'
|
3
|
+
require 'typhoeus'
|
4
|
+
require 'oauth/request_proxy/typhoeus_request'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
# The path to the lib directory.
|
8
|
+
FELLOWSHIPONE_LIB_DIR = File.dirname(__FILE__)
|
9
|
+
|
10
|
+
require File.dirname(__FILE__) + '/auto_load.rb'
|
11
|
+
|
12
|
+
require File.dirname(__FILE__) + '/common.rb'
|
13
|
+
|
14
|
+
require File.dirname(__FILE__) + '/oauth_monkey_patch'
|
15
|
+
|
16
|
+
module FellowshipOne
|
17
|
+
|
18
|
+
class Api
|
19
|
+
|
20
|
+
class << self
|
21
|
+
attr_reader :church_code, :consumer_key, :consumer_secret, :api_token, :api_secret, :is_production
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.establish_connection(church_code, consumer_key, consumer_secret, callback_url, production = true)
|
25
|
+
if church_code.nil? or consumer_key.nil? or consumer_secret.nil?
|
26
|
+
raise FellowshipOneExceptions::UnableToConnectToFellowshipOne.new('Church code, Consumer Key and Consumer Secret cannot be nil.')
|
27
|
+
end
|
28
|
+
|
29
|
+
consumer_env = production ? '' : '.staging' # Yes, blank is production
|
30
|
+
|
31
|
+
puts "F1 URL: https://#{church_code}#{consumer_env}.fellowshiponeapi.com"
|
32
|
+
|
33
|
+
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
|
34
|
+
:site => "https://#{church_code}#{consumer_env}.fellowshiponeapi.com",
|
35
|
+
:request_token_path => '/v1/Tokens/RequestToken',
|
36
|
+
:authorize_path => '/v1/PortalUser/Login',
|
37
|
+
:access_token_path => '/v1/Tokens/AccessToken')
|
38
|
+
|
39
|
+
consumer.get_request_token(:oauth_callback => callback_url)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.connect(church_code, consumer_key, consumer_secret, oauth_token, oauth_secret, production = true)
|
43
|
+
raise FellowshipOneExceptions::UnableToConnectToFellowshipOne.new('Church Code, Token and Secret cannot be nil.') if oauth_token.nil? or oauth_secret.nil?
|
44
|
+
@church_code = church_code
|
45
|
+
@consumer_key = consumer_key
|
46
|
+
@consumer_secret = consumer_secret
|
47
|
+
@api_token = oauth_token
|
48
|
+
@api_secret = oauth_secret
|
49
|
+
@is_production = production
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|