church-community-builder 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +52 -0
- data/README.rdoc +54 -0
- data/Rakefile +32 -0
- data/ccb_api.gemspec +26 -0
- data/docs/batch_implement.pdf +0 -0
- data/docs/event_implement.pdf +0 -0
- data/docs/group_implement.pdf +0 -0
- data/docs/individual_profile_implement.pdf +0 -0
- data/docs/pwt_implement.pdf +0 -0
- data/docs/pwt_overview.pdf +0 -0
- data/examples/batch.rb +50 -0
- data/examples/calendar.rb +18 -0
- data/examples/campus.rb +13 -0
- data/examples/individual.rb +38 -0
- data/examples/sync_data.rb +48 -0
- data/lib/api/address.rb +28 -0
- data/lib/api/api_object.rb +116 -0
- data/lib/api/batch.rb +48 -0
- data/lib/api/batch_list.rb +50 -0
- data/lib/api/campus.rb +29 -0
- data/lib/api/campus_list.rb +65 -0
- data/lib/api/individual.rb +138 -0
- data/lib/api/individual_list.rb +65 -0
- data/lib/api/mergeable_individual_list.rb +92 -0
- data/lib/api/mergeable_transaction_list.rb +74 -0
- data/lib/api/search.rb +81 -0
- data/lib/api/transaction.rb +114 -0
- data/lib/api/transaction_list.rb +52 -0
- data/lib/api/valid_individual.rb +43 -0
- data/lib/api/valid_individual_list.rb +49 -0
- data/lib/auto_load.rb +17 -0
- data/lib/ccb_api.rb +33 -0
- data/lib/common.rb +41 -0
- data/lib/exceptions.rb +5 -0
- data/lib/readers/api_reader.rb +35 -0
- data/lib/readers/batch_list_reader.rb +17 -0
- data/lib/readers/batch_reader.rb +14 -0
- data/lib/readers/campus_list_reader.rb +17 -0
- data/lib/readers/individual_list_reader.rb +18 -0
- data/lib/readers/individual_reader.rb +14 -0
- data/lib/writers/api_writer.rb +64 -0
- data/lib/writers/user_writer.rb +46 -0
- data/spec/api/user_spec.rb +37 -0
- data/spec/factories/user.rb +51 -0
- data/spec/functional/ccb_spec.rb +20 -0
- data/spec/readers/user_reader_spec.rb +7 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/writers/user_writer_spec.rb +80 -0
- metadata +137 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
module ChurchCommunityBuilder
|
2
|
+
|
3
|
+
class MergeableTransactionList
|
4
|
+
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_reader :transaction_array #for debugging
|
8
|
+
|
9
|
+
|
10
|
+
def initialize(transaction_list = nil)
|
11
|
+
|
12
|
+
if transaction_list.nil?
|
13
|
+
@transaction_array = []
|
14
|
+
|
15
|
+
else
|
16
|
+
@transaction_array = transaction_list.transaction_array
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def all_names
|
23
|
+
return [] unless @transaction_array
|
24
|
+
@transaction_array.collect { |transaction| transaction['individual']['content'] }
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](index)
|
28
|
+
Transaction.new( @transaction_array[index] ) if @transaction_array and @transaction_array[index]
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
# This method is needed for Enumerable.
|
33
|
+
def each &block
|
34
|
+
@transaction_array.each{ |transaction| yield( Transaction.new(transaction) )}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get all the Transaction ids in the list.
|
38
|
+
#
|
39
|
+
# @return An array of Transaction ids.
|
40
|
+
def ids
|
41
|
+
(@transaction_array.collect { |transaction| transaction['id'] }).uniq
|
42
|
+
end
|
43
|
+
|
44
|
+
# Adds an TransactionList, MergeableTransactionList, or Transaction to this list.
|
45
|
+
#
|
46
|
+
def add(transaction_type)
|
47
|
+
|
48
|
+
if transaction_type.is_a?(TransactionList)
|
49
|
+
@transaction_array += transaction_type.transaction_array
|
50
|
+
|
51
|
+
elsif transaction_type.is_a?(MergeableTransactionList)
|
52
|
+
@transaction_array += transaction_type.transaction_array
|
53
|
+
|
54
|
+
elsif transaction_type.is_a?(Transaction)
|
55
|
+
@transaction_array << JSON.parse( transaction_type.to_json )
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
alias_method :merge, :add
|
62
|
+
|
63
|
+
def count
|
64
|
+
@transaction_array.size
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def empty?
|
69
|
+
self.count == 0 ? true : false
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
data/lib/api/search.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
module ChurchCommunityBuilder
|
2
|
+
|
3
|
+
class Search
|
4
|
+
|
5
|
+
# Search CCB for individuals based off of the search parameters
|
6
|
+
# Note:
|
7
|
+
# Searches are performed as a LIKE query in the CCB database.
|
8
|
+
# If the value provided for the criterion is found anywhere in the field,
|
9
|
+
# it will be considered a match.
|
10
|
+
def self.search_for_person_by_name(last_name = nil,first_name = nil)
|
11
|
+
options = {:url_data_params => {srv: "individual_search",
|
12
|
+
last_name: last_name,
|
13
|
+
first_name: first_name
|
14
|
+
}
|
15
|
+
}
|
16
|
+
reader = IndividualListReader.new(options)
|
17
|
+
IndividualList.new(reader.load_feed)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a list of all individuals in the Church Community Builder system.
|
21
|
+
def self.search_for_all_valid_individuals
|
22
|
+
options = {:url_data_params => {srv: "valid_individuals" }
|
23
|
+
|
24
|
+
}
|
25
|
+
reader = IndividualListReader.new(options)
|
26
|
+
ValidIndividualList.new(reader.load_feed)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Leaving 'modified_since' as 'nil' will return all
|
30
|
+
# batches in the system.
|
31
|
+
#
|
32
|
+
# Specifying a date will return all batches created
|
33
|
+
# or modified since that date.
|
34
|
+
#
|
35
|
+
# Date format should be YYYY-MM-DD
|
36
|
+
def self.search_for_batch_by_date(modified_since = nil)
|
37
|
+
options = {:url_data_params => {srv: "batch_profiles",
|
38
|
+
modified_since: modified_since
|
39
|
+
}
|
40
|
+
}
|
41
|
+
reader = BatchListReader.new(options)
|
42
|
+
BatchList.new(reader.load_feed)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns a BatchList of all batches posted in specified date range.
|
46
|
+
# End date is optional.
|
47
|
+
#
|
48
|
+
# Date format should be YYYY-MM-DD
|
49
|
+
def self.search_for_batch_by_date_range(start_date, end_date = nil)
|
50
|
+
options = {:url_data_params => {srv: "batch_profiles_in_date_range",
|
51
|
+
date_start: start_date,
|
52
|
+
date_end: end_date
|
53
|
+
}
|
54
|
+
}
|
55
|
+
options[:url_data_params].delete(:date_end) if end_date.nil?
|
56
|
+
reader = BatchListReader.new(options)
|
57
|
+
BatchList.new(reader.load_feed)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.search_for_batch_by_id(batch_id)
|
61
|
+
# options = {:url_data_params => {srv: "batch_profile_from_id",
|
62
|
+
# id: batch_id
|
63
|
+
# }
|
64
|
+
# }
|
65
|
+
reader = BatchReader.new(batch_id)
|
66
|
+
Batch.new(reader.load_feed)
|
67
|
+
end
|
68
|
+
|
69
|
+
# This is currently undocumented, but found via spelunking
|
70
|
+
#
|
71
|
+
def self.search_for_all_campuses
|
72
|
+
options = {:url_data_params => {srv: "campus_list" }
|
73
|
+
|
74
|
+
}
|
75
|
+
reader = CampusListReader.new(options)
|
76
|
+
CampusList.new(reader.load_feed)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module ChurchCommunityBuilder
|
2
|
+
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
class Transaction < ApiObject
|
6
|
+
|
7
|
+
ccb_attr_accessor :id,
|
8
|
+
:campus,
|
9
|
+
:individual,
|
10
|
+
:date,
|
11
|
+
:grouping,
|
12
|
+
:payment_type,
|
13
|
+
:check_number,
|
14
|
+
:transaction_details,
|
15
|
+
:creator,
|
16
|
+
:modifier,
|
17
|
+
:created,
|
18
|
+
:modified
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
def initialize(json_data = nil, options = {})
|
23
|
+
initialize_from_json_object(json_data) unless json_data.nil?
|
24
|
+
|
25
|
+
if json_data["transaction"].nil?
|
26
|
+
transaction_json = json_data
|
27
|
+
else
|
28
|
+
transaction_json = json_data["transaction"]
|
29
|
+
end
|
30
|
+
|
31
|
+
initialize_from_json_object(transaction_json) unless transaction_json.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def campus_id
|
35
|
+
self.campus["id"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def campus_name
|
39
|
+
self.campus["content"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def individual_id
|
43
|
+
self.individual["id"]
|
44
|
+
end
|
45
|
+
|
46
|
+
def individual_name
|
47
|
+
self.individual["content"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def multiple_transactions?
|
51
|
+
self.transaction_details["transaction_detail"].is_a?(Array)
|
52
|
+
end
|
53
|
+
|
54
|
+
def transaction_detail_id
|
55
|
+
if multiple_transactions?
|
56
|
+
self.transaction_details["transaction_detail"].each{ |trans| trans["id"] }
|
57
|
+
else
|
58
|
+
self.transaction_details["transaction_detail"]["id"]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def fund_id
|
63
|
+
if multiple_transactions?
|
64
|
+
self.transaction_details["transaction_detail"].each{ |trans| trans["coa"]["id"] }
|
65
|
+
else
|
66
|
+
self.transaction_details["transaction_detail"]["coa"]["id"]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def fund_name
|
71
|
+
if multiple_transactions?
|
72
|
+
self.transaction_details["transaction_detail"].collect{ |trans| trans["coa"]["content"] }
|
73
|
+
else
|
74
|
+
self.transaction_details["transaction_detail"]["coa"]["content"]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def amount
|
79
|
+
if multiple_transactions?
|
80
|
+
self.transaction_details["transaction_detail"].collect{ |trans| trans["amount"] }
|
81
|
+
else
|
82
|
+
self.transaction_details["transaction_detail"]["amount"]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def as_splits
|
88
|
+
vals = []
|
89
|
+
if multiple_transactions?
|
90
|
+
self.transaction_details["transaction_detail"].each_with_index do |trans, indx|
|
91
|
+
vals << {:transaction_detail_id => trans['id'],
|
92
|
+
:fund_id => trans["coa"]["id"],
|
93
|
+
:fund_name => trans["coa"]["content"],
|
94
|
+
:amount => self.transaction_details["transaction_detail"][indx]["amount"]}
|
95
|
+
end
|
96
|
+
else
|
97
|
+
vals << {:transaction_detail_id => self.transaction_details["transaction_detail"]["id"],
|
98
|
+
:fund_id => self.transaction_details["transaction_detail"]["coa"]["id"],
|
99
|
+
:fund_name => self.transaction_details["transaction_detail"]["coa"]["content"],
|
100
|
+
:amount => self.transaction_details["transaction_detail"]["amount"]}
|
101
|
+
end
|
102
|
+
return vals
|
103
|
+
end
|
104
|
+
|
105
|
+
# def self.load_by_id(transaction_id)
|
106
|
+
# reader = TransactionReader.new(transaction_id)
|
107
|
+
# self.new(reader.load_feed)
|
108
|
+
# rescue
|
109
|
+
# nil
|
110
|
+
# end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ChurchCommunityBuilder
|
2
|
+
|
3
|
+
class TransactionList
|
4
|
+
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_reader :transaction_array #for debugging
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
def initialize(json_data)
|
12
|
+
|
13
|
+
# if @json_data['transaction'] is a single item, it will be returned
|
14
|
+
# as a Hash, rather than a single element Array, containing the Hash.
|
15
|
+
#
|
16
|
+
if json_data["transaction"].is_a?(Array)
|
17
|
+
@transaction_array = json_data["transaction"]
|
18
|
+
|
19
|
+
elsif json_data["transaction"].is_a?(Hash)
|
20
|
+
@transaction_array = []
|
21
|
+
@transaction_array << json_data["transaction"] #array of each transaction
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def all_names
|
27
|
+
return [] unless @transaction_array
|
28
|
+
@transaction_array.collect { |transaction| transaction['individual']['content'] }
|
29
|
+
end
|
30
|
+
|
31
|
+
def ids
|
32
|
+
(@transaction_array.collect { |transaction| transaction['id'] }).uniq
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](index)
|
36
|
+
Transaction.new( @transaction_array[index] ) if @transaction_array and @transaction_array[index]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# This method is needed for Enumerable.
|
41
|
+
def each &block
|
42
|
+
@transaction_array.each{ |transaction| yield( Transaction.new(transaction) )}
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def empty?
|
47
|
+
@transaction_array.size == 0 ? true : false
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ChurchCommunityBuilder
|
2
|
+
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
# A ValidIndividual is the data returned when querying CCB for 'valid_individuals'
|
6
|
+
# A ValidIndividual is largely metadata about the individual,
|
7
|
+
# as well as the inviduals ID. From the ID, the individual can be retrieved.
|
8
|
+
#
|
9
|
+
class ValidIndividual < ApiObject
|
10
|
+
|
11
|
+
ccb_attr_accessor :id,
|
12
|
+
:active,
|
13
|
+
:creator,
|
14
|
+
:modifier,
|
15
|
+
:created,
|
16
|
+
:modified
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(json_data = nil, options = {})
|
20
|
+
#@writer_object = PersonWriter
|
21
|
+
|
22
|
+
# When we initialize from IndividualReader, the "Individual" is buried
|
23
|
+
if json_data["ccb_api"].nil?
|
24
|
+
individual_json = json_data
|
25
|
+
else
|
26
|
+
individual_json = json_data["ccb_api"]["response"]["individuals"]["individual"]
|
27
|
+
end
|
28
|
+
|
29
|
+
initialize_from_json_object(individual_json) unless individual_json.nil?
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
# def self.load_by_id(individual_id)
|
34
|
+
# reader = IndividualReader.new(individual_id)
|
35
|
+
# self.new(reader.load_feed)
|
36
|
+
# rescue
|
37
|
+
# nil
|
38
|
+
# end
|
39
|
+
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ChurchCommunityBuilder
|
2
|
+
|
3
|
+
# A ValidIndividualList is returned when querying CCB for 'valid_individuals'
|
4
|
+
# A ValidIndividualList is largely metadata about the individual,
|
5
|
+
# as well as the inviduals ID. From here, an IndividualList can be built.
|
6
|
+
#
|
7
|
+
class ValidIndividualList
|
8
|
+
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
attr_reader :request_data,
|
12
|
+
:response_data,
|
13
|
+
:service,
|
14
|
+
:individuals,
|
15
|
+
:count,
|
16
|
+
:individual_array,
|
17
|
+
:json_data #for debugging
|
18
|
+
|
19
|
+
|
20
|
+
def initialize(json)
|
21
|
+
@json_data = json["ccb_api"]
|
22
|
+
@request_data = @json_data["request"]
|
23
|
+
@response_data = @json_data["response"]
|
24
|
+
@service = @response_data["service"] #CCB service type accessed
|
25
|
+
|
26
|
+
@individuals = @response_data['valid_individuals']
|
27
|
+
|
28
|
+
@count = @individuals["count"].to_i #number of records
|
29
|
+
@individual_array = @individuals['valid_individual'] #array of each individual
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](index)
|
33
|
+
ValidIndividual.new( @individual_array[index] ) if @individual_array and @individual_array[index]
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# This method is needed for Enumerable.
|
38
|
+
def each &block
|
39
|
+
@individual_array.each{ |individual| yield( ValidIndividual.new(individual) )}
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def empty?
|
44
|
+
self.count == 0 ? true : false
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/lib/auto_load.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module ChurchCommunityBuilder
|
2
|
+
|
3
|
+
require CCB_LIB_DIR + '/exceptions.rb'
|
4
|
+
|
5
|
+
api_path = CCB_LIB_DIR + '/api/'
|
6
|
+
require api_path + 'api_object.rb'
|
7
|
+
Dir["#{api_path}/*.rb"].each { |f| require(f) }
|
8
|
+
|
9
|
+
readers_path = CCB_LIB_DIR + '/readers/'
|
10
|
+
require readers_path + 'api_reader.rb'
|
11
|
+
Dir["#{readers_path}/*.rb"].each { |f| require(f) }
|
12
|
+
|
13
|
+
writers_path = CCB_LIB_DIR + '/writers/'
|
14
|
+
require writers_path + 'api_writer.rb'
|
15
|
+
Dir["#{writers_path}/*.rb"].each { |f| require(f) }
|
16
|
+
|
17
|
+
end
|
data/lib/ccb_api.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
require 'json'
|
3
|
+
require 'xmlsimple'
|
4
|
+
require 'active_support/core_ext'
|
5
|
+
|
6
|
+
# The path to the lib directory.
|
7
|
+
CCB_LIB_DIR = File.dirname(__FILE__)
|
8
|
+
|
9
|
+
require File.dirname(__FILE__) + '/auto_load.rb'
|
10
|
+
|
11
|
+
require File.dirname(__FILE__) + '/common.rb'
|
12
|
+
|
13
|
+
CCB_ENV = 'production' unless defined?(CCB_ENV)
|
14
|
+
|
15
|
+
# This class is meant to be a wrapper ChurchCommunityBuilder API
|
16
|
+
module ChurchCommunityBuilder
|
17
|
+
|
18
|
+
class Api
|
19
|
+
class << self
|
20
|
+
attr_reader :api_username, :api_password, :api_subdomain
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.connect(username, password, subdomain)
|
24
|
+
raise ChurchCommunityBuilderExceptions::UnableToConnectToChurchCommunityBuilder.new('Username, password, and subdomain cannot be nil.') if username.nil? or password.nil? or subdomain.nil?
|
25
|
+
@api_username = username
|
26
|
+
@api_password = password
|
27
|
+
@api_subdomain = subdomain
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|