virtuous 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/test.yml +26 -0
- data/.gitignore +5 -0
- data/.reek.yml +36 -0
- data/.rubocop.yml +87 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/README.md +54 -0
- data/Rakefile +24 -0
- data/lib/virtuous/client/contact.rb +220 -0
- data/lib/virtuous/client/contact_address.rb +78 -0
- data/lib/virtuous/client/gift.rb +394 -0
- data/lib/virtuous/client/gift_designation.rb +59 -0
- data/lib/virtuous/client/individual.rb +125 -0
- data/lib/virtuous/client/recurring_gift.rb +86 -0
- data/lib/virtuous/client.rb +272 -0
- data/lib/virtuous/error.rb +54 -0
- data/lib/virtuous/helpers/hash_helper.rb +28 -0
- data/lib/virtuous/helpers/string_helper.rb +31 -0
- data/lib/virtuous/parse_oj.rb +24 -0
- data/lib/virtuous/version.rb +5 -0
- data/lib/virtuous.rb +12 -0
- data/logo/virtuous.svg +1 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/client_factory.rb +10 -0
- data/spec/support/fixtures/contact.json +112 -0
- data/spec/support/fixtures/contact_address.json +20 -0
- data/spec/support/fixtures/contact_addresses.json +42 -0
- data/spec/support/fixtures/contact_gifts.json +80 -0
- data/spec/support/fixtures/gift.json +55 -0
- data/spec/support/fixtures/gift_designation_query_options.json +2701 -0
- data/spec/support/fixtures/gift_designations.json +175 -0
- data/spec/support/fixtures/gifts.json +112 -0
- data/spec/support/fixtures/import.json +0 -0
- data/spec/support/fixtures/individual.json +46 -0
- data/spec/support/fixtures/recurring_gift.json +26 -0
- data/spec/support/fixtures_helper.rb +5 -0
- data/spec/support/virtuous_mock.rb +101 -0
- data/spec/virtuous/client_spec.rb +270 -0
- data/spec/virtuous/error_spec.rb +74 -0
- data/spec/virtuous/resources/contact_address_spec.rb +75 -0
- data/spec/virtuous/resources/contact_spec.rb +137 -0
- data/spec/virtuous/resources/gift_designation_spec.rb +70 -0
- data/spec/virtuous/resources/gift_spec.rb +249 -0
- data/spec/virtuous/resources/individual_spec.rb +95 -0
- data/spec/virtuous/resources/recurring_gift_spec.rb +67 -0
- data/spec/virtuous_spec.rb +7 -0
- data/virtuous.gemspec +25 -0
- metadata +121 -0
@@ -0,0 +1,394 @@
|
|
1
|
+
module Virtuous
|
2
|
+
class Client
|
3
|
+
##
|
4
|
+
# ### Gift data
|
5
|
+
#
|
6
|
+
# {
|
7
|
+
# contact_id: [Integer],
|
8
|
+
# gift_type: [String],
|
9
|
+
# gift_date: [Time],
|
10
|
+
# amount: [Float],
|
11
|
+
# transaction_source: [String],
|
12
|
+
# transaction_id: [String],
|
13
|
+
# batch: [String],
|
14
|
+
# segment_id: [Integer],
|
15
|
+
# receipt_segment_id: [Integer],
|
16
|
+
# media_outlet_id: [Integer],
|
17
|
+
# notes: [String],
|
18
|
+
# is_private: [Boolean],
|
19
|
+
# receipt_date: [Time],
|
20
|
+
# contact_individual_id: [Integer],
|
21
|
+
# contact_passthrough_id: [Integer],
|
22
|
+
# cash_accounting_code: [String],
|
23
|
+
# state: [String],
|
24
|
+
# is_tax_deductible: [Boolean],
|
25
|
+
# gift_ask_id: [Integer],
|
26
|
+
# passthrough_gift_ask_id: [Integer],
|
27
|
+
# grant_id: [Integer],
|
28
|
+
# contact_membership_id: [Integer],
|
29
|
+
# currency_code: [String],
|
30
|
+
# exchange_rate: [Float],
|
31
|
+
# check_number: [String],
|
32
|
+
# credit_card_type: [String],
|
33
|
+
# cryptocoin_type: [String],
|
34
|
+
# transaction_hash: [String],
|
35
|
+
# coin_sold_for_cash: [Boolean],
|
36
|
+
# coin_amount: [Float],
|
37
|
+
# date_coin_was_sold: [Time],
|
38
|
+
# coin_sale_amount: [Float],
|
39
|
+
# ticker_symbol: [String],
|
40
|
+
# number_of_shares: [Float],
|
41
|
+
# ira_custodian: [String],
|
42
|
+
# stock_sold_for_cash: [Boolean],
|
43
|
+
# date_stock_was_sold: [Time],
|
44
|
+
# stock_sale_amount: [Float],
|
45
|
+
# non_cash_gift_type_id: [Integer],
|
46
|
+
# non_cash_gift_type: [String],
|
47
|
+
# description: [String],
|
48
|
+
# non_cash_sold_for_cash: [Boolean],
|
49
|
+
# date_non_cash_was_sold: [Time],
|
50
|
+
# non_cash_original_amount: [Float],
|
51
|
+
# non_cash_sale_amount: [Float],
|
52
|
+
# gift_designations: [
|
53
|
+
# {
|
54
|
+
# project_id: [Integer],
|
55
|
+
# amount: [Float],
|
56
|
+
# state: [String]
|
57
|
+
# }
|
58
|
+
# ],
|
59
|
+
# gift_premiums: [
|
60
|
+
# {
|
61
|
+
# premium_id: [Integer],
|
62
|
+
# quantity: [Integer],
|
63
|
+
# state: [String]
|
64
|
+
# }
|
65
|
+
# ],
|
66
|
+
# pledge_payments: [
|
67
|
+
# {
|
68
|
+
# id: [Integer],
|
69
|
+
# amount: [Float],
|
70
|
+
# state: [String]
|
71
|
+
# }
|
72
|
+
# ],
|
73
|
+
# recurring_gift_payments: [
|
74
|
+
# {
|
75
|
+
# id: [Integer],
|
76
|
+
# amount: [Float],
|
77
|
+
# state: [String]
|
78
|
+
# }
|
79
|
+
# ],
|
80
|
+
# tribute_type: [String],
|
81
|
+
# tribute_id: [Integer],
|
82
|
+
# tribute_description: [String],
|
83
|
+
# acknowledgee_id: [Integer],
|
84
|
+
# reversed_gift_id: [Integer],
|
85
|
+
# custom_fields: [
|
86
|
+
# {
|
87
|
+
# name: [String],
|
88
|
+
# value: [String],
|
89
|
+
# display_name: [String]
|
90
|
+
# }
|
91
|
+
# ]
|
92
|
+
# }
|
93
|
+
#
|
94
|
+
module Gift
|
95
|
+
##
|
96
|
+
# Gets the gifts made by a contact.
|
97
|
+
#
|
98
|
+
# @example
|
99
|
+
# client.get_contact_gifts(1, take: 10)
|
100
|
+
#
|
101
|
+
# @param contact_id [Integer] The id of the Contact.
|
102
|
+
# @option options [String] :sort_by The field to be sorted. Supported: `Id`, `GiftDate`,
|
103
|
+
# `Amount`, `Batch`, `CreatedDateTime`.
|
104
|
+
# @option options [Boolean] :descending The direction to be sorted.
|
105
|
+
# @option options [Integer] :skip The number of records to skip. Default = 0.
|
106
|
+
# @option options [Integer] :take The number of records to take. Default = 10.
|
107
|
+
#
|
108
|
+
# @return [Hash] A hash with a list of gifts and the total amount of gifts belonging to the
|
109
|
+
# contact
|
110
|
+
# @example Output
|
111
|
+
# { list: [...], total: n }
|
112
|
+
#
|
113
|
+
def get_contact_gifts(contact_id, **options)
|
114
|
+
options = options.slice(:sort_by, :descending, :skip, :take)
|
115
|
+
|
116
|
+
parse(get(
|
117
|
+
"api/Gift/ByContact/#{contact_id}",
|
118
|
+
format(options)
|
119
|
+
))
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Fetches a gift record by id.
|
124
|
+
#
|
125
|
+
# @example
|
126
|
+
# client.get_gift(1)
|
127
|
+
#
|
128
|
+
# @param id [Integer] The id of the gift.
|
129
|
+
#
|
130
|
+
# @return [Hash] The gift information in a hash.
|
131
|
+
def get_gift(id)
|
132
|
+
parse(get("api/Gift/#{id}"))
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Fetches a gift record by transaction id.
|
137
|
+
#
|
138
|
+
# @example
|
139
|
+
# client.find_gift_by_transaction_id('source', 1)
|
140
|
+
#
|
141
|
+
# @param transaction_source [String] The source of the transaction.
|
142
|
+
# @param transaction_id [Integer, String] The id of the transaction.
|
143
|
+
#
|
144
|
+
# @return [Hash] The gift information in a hash.
|
145
|
+
def find_gift_by_transaction_id(transaction_source, transaction_id)
|
146
|
+
encoded_id = transaction_id.is_a?(String) ? encode(transaction_id) : transaction_id
|
147
|
+
parse(get("api/Gift/#{encode(transaction_source)}/#{encoded_id}"))
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# Creates a gift.
|
152
|
+
#
|
153
|
+
# @example
|
154
|
+
# client.create_gift(
|
155
|
+
# contact_id: 1, gift_type: 'Cash', amount: 10.5, currency_code: 'USD',
|
156
|
+
# gift_date: Date.today
|
157
|
+
# )
|
158
|
+
#
|
159
|
+
# @param data [Hash] A hash containing the gift details.
|
160
|
+
# Refer to the [Gift data](#label-Gift+data) section
|
161
|
+
# above to see the available attributes.
|
162
|
+
#
|
163
|
+
# @return [Hash] The gift that has been created.
|
164
|
+
def create_gift(data)
|
165
|
+
parse(post('api/Gift', format(data)))
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Creates gifts in bulks of up to 100 at a time.
|
170
|
+
#
|
171
|
+
# @example
|
172
|
+
# client.create_gifts([
|
173
|
+
# {
|
174
|
+
# contact_id: 1, gift_type: 'Cash', amount: 10.5, currency_code: 'USD',
|
175
|
+
# gift_date: Date.today
|
176
|
+
# },
|
177
|
+
# {
|
178
|
+
# contact_id: 2, gift_type: 'Cash', amount: 5.0, currency_code: 'USD',
|
179
|
+
# gift_date: Date.today
|
180
|
+
# }
|
181
|
+
# ])
|
182
|
+
#
|
183
|
+
# @param gifts [Array] An array of gifts.
|
184
|
+
# Refer to the [Gift data](#label-Gift+data) section
|
185
|
+
# above to see the available attributes.
|
186
|
+
#
|
187
|
+
# @return [Array] An array of gifts.
|
188
|
+
def create_gifts(gifts)
|
189
|
+
request_body = gifts.map { |gift| format(gift) }
|
190
|
+
response = post('api/Gift/Bulk', request_body)
|
191
|
+
response.map { |gift| parse(gift) }
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
195
|
+
# Updates a gift.
|
196
|
+
#
|
197
|
+
# @example
|
198
|
+
# client.update_gift(
|
199
|
+
# 1, gift_type: 'Cash', amount: 5.0, currency_code: 'USD',
|
200
|
+
# gift_date: Date.today
|
201
|
+
# )
|
202
|
+
#
|
203
|
+
# @note Excluding a property will remove it's value from the object.
|
204
|
+
# If you're only updating a single property, the entire model is still required.
|
205
|
+
#
|
206
|
+
# @param id [Integer] The id of the gift to update.
|
207
|
+
# @param data [Hash] A hash containing the gift details.
|
208
|
+
# Refer to the [Gift data](#label-Gift+data) section
|
209
|
+
# above to see the available attributes.
|
210
|
+
#
|
211
|
+
# @return [Hash] The gift that has been updated.
|
212
|
+
def update_gift(id, data)
|
213
|
+
parse(put("api/Gift/#{id}", format(data)))
|
214
|
+
end
|
215
|
+
|
216
|
+
##
|
217
|
+
# Delete a gift.
|
218
|
+
#
|
219
|
+
# @example
|
220
|
+
# client.delete_gift(1)
|
221
|
+
#
|
222
|
+
# @param id [Integer] The id of the gift to delete.
|
223
|
+
def delete_gift(id)
|
224
|
+
delete("api/Gift/#{id}")
|
225
|
+
end
|
226
|
+
|
227
|
+
##
|
228
|
+
# Creates a gift. This ensures the gift is matched using the Virtuous matching algorithms
|
229
|
+
# for Contacts, Recurring gifts, Designations, etc.
|
230
|
+
#
|
231
|
+
# Transactions are posted to the API and are set to a holding state.
|
232
|
+
# At midnight, transactions are bundled into imports based on the source they were posted
|
233
|
+
# with.
|
234
|
+
# The organization reviews the imported transactions, and then clicks run.
|
235
|
+
#
|
236
|
+
# @example
|
237
|
+
# client.import_gift(
|
238
|
+
# gift_type: 'Cash', amount: 10.5, currency_code: 'USD', gift_date: Date.today,
|
239
|
+
# contact: {
|
240
|
+
# contact_type: 'Organization', name: 'Org name', first_name: 'John',
|
241
|
+
# last_name: 'Doe', email: 'john_doe@email.com'
|
242
|
+
# }
|
243
|
+
# )
|
244
|
+
#
|
245
|
+
# @param data [Hash] A hash containing the gift details.
|
246
|
+
#
|
247
|
+
# #### Full list of accepted fields
|
248
|
+
#
|
249
|
+
# {
|
250
|
+
# transaction_source: [String],
|
251
|
+
# transaction_id: [String],
|
252
|
+
# contact: [Contact],
|
253
|
+
# gift_date: [String],
|
254
|
+
# cancel_date: [String],
|
255
|
+
# gift_type: [String],
|
256
|
+
# amount: [String],
|
257
|
+
# currency_code: [String],
|
258
|
+
# exchange_rate: [Float],
|
259
|
+
# frequency: [String],
|
260
|
+
# recurring_gift_transaction_id: [String],
|
261
|
+
# recurring_gift_transaction_update: [Boolean],
|
262
|
+
# pledge_frequency: [String],
|
263
|
+
# pledge_transaction_id: [String],
|
264
|
+
# pledge_expected_fullfillment_date: [String],
|
265
|
+
# batch: [String],
|
266
|
+
# notes: [String],
|
267
|
+
# segment: [String],
|
268
|
+
# media_outlet: [String],
|
269
|
+
# receipt_date: [String],
|
270
|
+
# receipt_segment: [String],
|
271
|
+
# cash_accounting_code: [String],
|
272
|
+
# tribute: [String],
|
273
|
+
# tribute_dedication: {
|
274
|
+
# tribute_id: [Integer],
|
275
|
+
# tribute_type: [String],
|
276
|
+
# tribute_first_name: [String],
|
277
|
+
# tribute_last_name: [String],
|
278
|
+
# tribute_city: [String],
|
279
|
+
# tribute_state: [String],
|
280
|
+
# acknowledgee_individual_id: [Integer],
|
281
|
+
# acknowledgee_first_name: [String],
|
282
|
+
# acknowledgee_last_name: [String],
|
283
|
+
# acknowledgee_address: [String],
|
284
|
+
# acknowledgee_city: [String],
|
285
|
+
# acknowledgee_state: [String],
|
286
|
+
# acknowledgee_postal: [String],
|
287
|
+
# acknowledgee_email: [String],
|
288
|
+
# acknowledgee_phone: [String]
|
289
|
+
# },
|
290
|
+
# is_private: [Boolean],
|
291
|
+
# is_tax_deductible: [Boolean],
|
292
|
+
# check_number: [String],
|
293
|
+
# credit_card_type: [String],
|
294
|
+
# non_cash_gift_type_id: [Integer],
|
295
|
+
# non_cash_gift_type: [String],
|
296
|
+
# non_cash_gift_description: [String],
|
297
|
+
# stock_ticker_symbol: [String],
|
298
|
+
# stock_number_of_shares: [Integer],
|
299
|
+
# ira_custodian: [String],
|
300
|
+
# submission_url: [String],
|
301
|
+
# designations: [
|
302
|
+
# {
|
303
|
+
# id: [Integer],
|
304
|
+
# name: [String],
|
305
|
+
# code: [String],
|
306
|
+
# amount_designated: [String]
|
307
|
+
# }
|
308
|
+
# ],
|
309
|
+
# premiums: [
|
310
|
+
# {
|
311
|
+
# id: [Integer],
|
312
|
+
# name: [String],
|
313
|
+
# code: [String],
|
314
|
+
# quantity: [String]
|
315
|
+
# }
|
316
|
+
# ],
|
317
|
+
# custom_fields: [Hash],
|
318
|
+
# custom_objects: [
|
319
|
+
# {
|
320
|
+
# name: [String],
|
321
|
+
# fields: [
|
322
|
+
# {
|
323
|
+
# name: [String],
|
324
|
+
# value: [String]
|
325
|
+
# }
|
326
|
+
# ]
|
327
|
+
# }
|
328
|
+
# ],
|
329
|
+
# contact_individual_id: [Integer],
|
330
|
+
# passthrough_contact: [Contact],
|
331
|
+
# event_attendee: {
|
332
|
+
# event_id: [Integer],
|
333
|
+
# event_name: [String],
|
334
|
+
# invited: [Boolean],
|
335
|
+
# rsvp: [Boolean],
|
336
|
+
# rsvp_response: [Boolean],
|
337
|
+
# attended: [Boolean]
|
338
|
+
# }
|
339
|
+
# }
|
340
|
+
#
|
341
|
+
def import_gift(data)
|
342
|
+
post('api/v2/Gift/Transaction', format(data))
|
343
|
+
end
|
344
|
+
|
345
|
+
##
|
346
|
+
# Creates a batch of gift transactions. This ensures the gift is matched using the Virtuous
|
347
|
+
# matching algorithms for Contacts, Recurring gifts, Designations, etc.
|
348
|
+
#
|
349
|
+
# Transactions are posted to the API and are set to a holding state.
|
350
|
+
# At midnight, transactions are bundled into imports based on the source they were posted
|
351
|
+
# with.
|
352
|
+
# The organization reviews the imported transactions, and then clicks run.
|
353
|
+
#
|
354
|
+
# @example
|
355
|
+
# client.import_gifts(
|
356
|
+
# transaction_source: 'Source', transactions: [
|
357
|
+
# {
|
358
|
+
# gift_type: 'Cash', amount: 10.5, currency_code: 'USD', gift_date: Date.today,
|
359
|
+
# contact: {
|
360
|
+
# contact_type: 'Organization', name: 'Org name', first_name: 'John',
|
361
|
+
# last_name: 'Doe', email: 'john_doe@email.com'
|
362
|
+
# }
|
363
|
+
# },
|
364
|
+
# {
|
365
|
+
# gift_type: 'Cash', amount: 5.0, currency_code: 'USD', gift_date: Date.today,
|
366
|
+
# contact: {
|
367
|
+
# contact_type: 'Organization', name: 'Org name', first_name: 'John',
|
368
|
+
# last_name: 'Doe', email: 'john_doe@email.com'
|
369
|
+
# }
|
370
|
+
# }
|
371
|
+
# ]
|
372
|
+
# )
|
373
|
+
#
|
374
|
+
# @param transactions [Array] An array of gifts. Refer to {#import_gift}
|
375
|
+
# to see a full list of accepted fields.
|
376
|
+
# @param shared_fields [Hash] Shared fields for the transactions.
|
377
|
+
# @option shared_fields [String] :transaction_source
|
378
|
+
# @option shared_fields [Boolean] :create_import
|
379
|
+
# @option shared_fields [String] :import_name
|
380
|
+
# @option shared_fields [String] :batch
|
381
|
+
# @option shared_fields [Float] :batch_total
|
382
|
+
# @option shared_fields [String] :default_gift_date
|
383
|
+
# @option shared_fields [String] :default_gift_type
|
384
|
+
def import_gifts(transactions:, **shared_fields)
|
385
|
+
shared_fields = shared_fields.slice(
|
386
|
+
:transaction_source, :create_import, :import_name, :batch, :batch_total,
|
387
|
+
:default_gift_date, :default_gift_type
|
388
|
+
)
|
389
|
+
|
390
|
+
post('api/v2/Gift/Transactions', format(shared_fields.merge(transactions: transactions)))
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Virtuous
|
2
|
+
class Client
|
3
|
+
module GiftDesignation
|
4
|
+
##
|
5
|
+
# Queries a list of available gift designation query options.
|
6
|
+
# @return [Hash] A list of available gift designation query options.
|
7
|
+
def gift_designation_query_options
|
8
|
+
parse(get('api/GiftDesignation/QueryOptions'))
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# Queries gift designations.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# client.query_gift_designations(
|
16
|
+
# take: 5, skip: 0, sort_by: 'Id',
|
17
|
+
# conditions: [{ parameter: 'Gift Id', operator: 'Is', value: 102 }]
|
18
|
+
# )
|
19
|
+
#
|
20
|
+
# @option options [Integer] :take The maximum amount of designations to query. Default: 10.
|
21
|
+
# Max is 1000.
|
22
|
+
# @option options [Integer] :skip The number of designations to skip. Default: 0.
|
23
|
+
# @option options [String] :sort_by The value to sort records by.
|
24
|
+
# You can sort by Id, Amount, GiftDate, ReceiptDate and Batch.
|
25
|
+
# @option options [Boolean] :descending If true the records will be sorted in descending
|
26
|
+
# order.
|
27
|
+
# @option options [Array] :conditions An array of conditions to filter the gift designation.
|
28
|
+
# Use {gift_designation_query_options} to see
|
29
|
+
# a full list of available conditions.
|
30
|
+
#
|
31
|
+
# @return [Hash] A hash with a list and the total amount of gift designations that satisfy
|
32
|
+
# the conditions.
|
33
|
+
# @example Output
|
34
|
+
# { list: [...], total: n }
|
35
|
+
#
|
36
|
+
def query_gift_designations(**options)
|
37
|
+
uri = URI('api/GiftDesignation/Query')
|
38
|
+
query_params = options.slice(:take, :skip)
|
39
|
+
uri.query = URI.encode_www_form(query_params) unless query_params.empty?
|
40
|
+
|
41
|
+
parse(post(uri, format(query_gift_designations_body(options))))
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def query_gift_designations_body(options)
|
47
|
+
conditions = options[:conditions]
|
48
|
+
body = options.slice(:sort_by, :descending)
|
49
|
+
return body if conditions.nil?
|
50
|
+
|
51
|
+
body.merge({
|
52
|
+
groups: [{
|
53
|
+
conditions: conditions
|
54
|
+
}]
|
55
|
+
})
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Virtuous
|
2
|
+
class Client
|
3
|
+
##
|
4
|
+
# ### Individual data
|
5
|
+
#
|
6
|
+
# {
|
7
|
+
# contact_id: [Integer],
|
8
|
+
# first_name: [String],
|
9
|
+
# last_name: [String],
|
10
|
+
# contact_methods: [
|
11
|
+
# {
|
12
|
+
# type: [String],
|
13
|
+
# value: [String],
|
14
|
+
# is_opted_in: [Boolean],
|
15
|
+
# is_primary: [Boolean]
|
16
|
+
# }
|
17
|
+
# ],
|
18
|
+
# prefix: [String],
|
19
|
+
# middle_name: [String],
|
20
|
+
# suffix: [String],
|
21
|
+
# gender: [String],
|
22
|
+
# set_as_primary: [Boolean],
|
23
|
+
# set_as_secondary: [Boolean],
|
24
|
+
# birth_month: [Integer],
|
25
|
+
# birth_day: [Integer],
|
26
|
+
# birth_year: [Integer],
|
27
|
+
# approximate_age: [Integer],
|
28
|
+
# is_deceased: [Boolean],
|
29
|
+
# deceased_date: [Date],
|
30
|
+
# passion: [String],
|
31
|
+
# avatar_url: [String],
|
32
|
+
# custom_fields: [
|
33
|
+
# {
|
34
|
+
# name: [String],
|
35
|
+
# value: [String],
|
36
|
+
# display_name: [String]
|
37
|
+
# }
|
38
|
+
# ],
|
39
|
+
# custom_collections: [
|
40
|
+
# {
|
41
|
+
# name: [String],
|
42
|
+
# fields: [
|
43
|
+
# {
|
44
|
+
# name: [String],
|
45
|
+
# value: [String]
|
46
|
+
# }
|
47
|
+
# ]
|
48
|
+
# }
|
49
|
+
# ]
|
50
|
+
# }
|
51
|
+
#
|
52
|
+
module Individual
|
53
|
+
##
|
54
|
+
# Fetches an individual record by email.
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# client.find_individual_by_email('individual@email.com')
|
58
|
+
#
|
59
|
+
# @param email [String] The email of the individual.
|
60
|
+
#
|
61
|
+
# @return [Hash] The individual information in a hash.
|
62
|
+
def find_individual_by_email(email)
|
63
|
+
parse(get('api/ContactIndividual/Find', { email: email }))
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Fetches an individual record by id.
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# client.get_individual(1)
|
71
|
+
#
|
72
|
+
# @param id [Integer] The id of the individual.
|
73
|
+
#
|
74
|
+
# @return [Hash] The individual information in a hash.
|
75
|
+
def get_individual(id)
|
76
|
+
parse(get("api/ContactIndividual/#{id}"))
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Creates an individual.
|
81
|
+
#
|
82
|
+
# @example
|
83
|
+
# client.create_individual(first_name: 'John', last_name: 'Doe', contact_id: 1)
|
84
|
+
#
|
85
|
+
# @param data [Hash] A hash containing the individual details.
|
86
|
+
# Refer to the [Individual data](#label-Individual+data)
|
87
|
+
# section above to see the available attributes.
|
88
|
+
#
|
89
|
+
# @return [Hash] The individual that has been created.
|
90
|
+
def create_individual(data)
|
91
|
+
parse(post('api/ContactIndividual', format(data)))
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Updates an individual.
|
96
|
+
#
|
97
|
+
# @example
|
98
|
+
# client.update_individual(1, first_name: 'New', last_name: 'Name')
|
99
|
+
#
|
100
|
+
# @note Excluding a property will remove it's value from the object.
|
101
|
+
# If you're only updating a single property, the entire model is still required.
|
102
|
+
#
|
103
|
+
# @param id [Integer] The id of the individual to update.
|
104
|
+
# @param data [Hash] A hash containing the individual details.
|
105
|
+
# Refer to the [Individual data](#label-Individual+data)
|
106
|
+
# section above to see the available attributes.
|
107
|
+
#
|
108
|
+
# @return [Hash] The individual that has been updated.
|
109
|
+
def update_individual(id, data)
|
110
|
+
parse(put("api/ContactIndividual/#{id}", format(data)))
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Delete an individual.
|
115
|
+
#
|
116
|
+
# @example
|
117
|
+
# client.delete_individual(1)
|
118
|
+
#
|
119
|
+
# @param id [Integer] The id of the individual to delete.
|
120
|
+
def delete_individual(id)
|
121
|
+
delete("api/ContactIndividual/#{id}")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Virtuous
|
2
|
+
class Client
|
3
|
+
##
|
4
|
+
# ### Recurring Gift data
|
5
|
+
#
|
6
|
+
# {
|
7
|
+
# contactId: [Integer],
|
8
|
+
# startDate: [Time],
|
9
|
+
# frequency: [String],
|
10
|
+
# amount: [Float],
|
11
|
+
# nextExpectedPaymentDate: [Time],
|
12
|
+
# anticipatedEndDate: [Time],
|
13
|
+
# thankYouDate: [Time],
|
14
|
+
# segmentId: [Integer],
|
15
|
+
# automatedPayments: [Boolean],
|
16
|
+
# trackPayments: [Boolean],
|
17
|
+
# isPrivate: [Boolean],
|
18
|
+
# designations: [
|
19
|
+
# {
|
20
|
+
# projectId: [Integer],
|
21
|
+
# amountDesignated: [Float]
|
22
|
+
# }
|
23
|
+
# ],
|
24
|
+
# customFields: [
|
25
|
+
# {
|
26
|
+
# name: [String],
|
27
|
+
# value: [String],
|
28
|
+
# displayName: [String]
|
29
|
+
# }
|
30
|
+
# ]
|
31
|
+
# }
|
32
|
+
#
|
33
|
+
module RecurringGift
|
34
|
+
##
|
35
|
+
# Fetches a recurring gift record by id.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# client.get_recurring_gift(1)
|
39
|
+
#
|
40
|
+
# @param id [Integer] The id of the recurring gift.
|
41
|
+
#
|
42
|
+
# @return [Hash] The recurring gift information in a hash.
|
43
|
+
def get_recurring_gift(id)
|
44
|
+
parse(get("api/RecurringGift/#{id}"))
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Creates a recurring gift.
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# client.create_recurring_gift(
|
52
|
+
# contact_id: 1, start_date: Date.today, frequency: 'Monthly', amount: 1000
|
53
|
+
# )
|
54
|
+
#
|
55
|
+
# @param data [Hash] A hash containing the recurring gift details.
|
56
|
+
# Refer to the [Recurring Gift data](#label-Recurring+Gift+data)
|
57
|
+
# section above to see the available attributes.
|
58
|
+
#
|
59
|
+
# @return [Hash] The recurring gift that has been created.
|
60
|
+
def create_recurring_gift(data)
|
61
|
+
parse(post('api/RecurringGift', format(data)))
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Updates a recurring gift.
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# client.update_recurring_gift(
|
69
|
+
# 1, start_date: Date.today, frequency: 'Daily', amount: 500
|
70
|
+
# )
|
71
|
+
#
|
72
|
+
# @note Excluding a property will remove it's value from the object.
|
73
|
+
# If you're only updating a single property, the entire model is still required.
|
74
|
+
#
|
75
|
+
# @param id [Integer] The id of the recurring gift to update.
|
76
|
+
# @param data [Hash] A hash containing the recurring gift details.
|
77
|
+
# Refer to the [Gift data](#label-Recurring+Gift+data) section
|
78
|
+
# above to see the available attributes.
|
79
|
+
#
|
80
|
+
# @return [Hash] The recurring gift that has been updated.
|
81
|
+
def update_recurring_gift(id, data)
|
82
|
+
parse(put("api/RecurringGift/#{id}", format(data)))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|