virtuous 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|