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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yml +26 -0
  3. data/.gitignore +5 -0
  4. data/.reek.yml +36 -0
  5. data/.rubocop.yml +87 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/CHANGELOG.md +18 -0
  9. data/Gemfile +17 -0
  10. data/LICENSE +21 -0
  11. data/README.md +54 -0
  12. data/Rakefile +24 -0
  13. data/lib/virtuous/client/contact.rb +220 -0
  14. data/lib/virtuous/client/contact_address.rb +78 -0
  15. data/lib/virtuous/client/gift.rb +394 -0
  16. data/lib/virtuous/client/gift_designation.rb +59 -0
  17. data/lib/virtuous/client/individual.rb +125 -0
  18. data/lib/virtuous/client/recurring_gift.rb +86 -0
  19. data/lib/virtuous/client.rb +272 -0
  20. data/lib/virtuous/error.rb +54 -0
  21. data/lib/virtuous/helpers/hash_helper.rb +28 -0
  22. data/lib/virtuous/helpers/string_helper.rb +31 -0
  23. data/lib/virtuous/parse_oj.rb +24 -0
  24. data/lib/virtuous/version.rb +5 -0
  25. data/lib/virtuous.rb +12 -0
  26. data/logo/virtuous.svg +1 -0
  27. data/spec/spec_helper.rb +25 -0
  28. data/spec/support/client_factory.rb +10 -0
  29. data/spec/support/fixtures/contact.json +112 -0
  30. data/spec/support/fixtures/contact_address.json +20 -0
  31. data/spec/support/fixtures/contact_addresses.json +42 -0
  32. data/spec/support/fixtures/contact_gifts.json +80 -0
  33. data/spec/support/fixtures/gift.json +55 -0
  34. data/spec/support/fixtures/gift_designation_query_options.json +2701 -0
  35. data/spec/support/fixtures/gift_designations.json +175 -0
  36. data/spec/support/fixtures/gifts.json +112 -0
  37. data/spec/support/fixtures/import.json +0 -0
  38. data/spec/support/fixtures/individual.json +46 -0
  39. data/spec/support/fixtures/recurring_gift.json +26 -0
  40. data/spec/support/fixtures_helper.rb +5 -0
  41. data/spec/support/virtuous_mock.rb +101 -0
  42. data/spec/virtuous/client_spec.rb +270 -0
  43. data/spec/virtuous/error_spec.rb +74 -0
  44. data/spec/virtuous/resources/contact_address_spec.rb +75 -0
  45. data/spec/virtuous/resources/contact_spec.rb +137 -0
  46. data/spec/virtuous/resources/gift_designation_spec.rb +70 -0
  47. data/spec/virtuous/resources/gift_spec.rb +249 -0
  48. data/spec/virtuous/resources/individual_spec.rb +95 -0
  49. data/spec/virtuous/resources/recurring_gift_spec.rb +67 -0
  50. data/spec/virtuous_spec.rb +7 -0
  51. data/virtuous.gemspec +25 -0
  52. 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