patch_retention 0.2.2 → 0.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ff39a288451016541c8a8f63aca54115fb7f2a4e6a83daea5b503ebe7956fb5
4
- data.tar.gz: 6046dfe6d5692149f069ce54f14fd84bffb9139f3403710eb12c3050619f5130
3
+ metadata.gz: 109e3aa27d410ae2245f0b1de8a71a1531951869ff99e1c122e406c172e41c5b
4
+ data.tar.gz: 6666fdc1241ae1bb07fe9e5a014fd6f8c4950c9e9521ebb1c4d1e036c9135f03
5
5
  SHA512:
6
- metadata.gz: a3ea0a8fe3c04033678ebd81da8b003a995baa8515ebb2f518c459acf9a2d4d5f97ccb3499143ea4ee2f2595c3cdcad28b19d97620929e3a9834fad27b57d1f6
7
- data.tar.gz: d4c4fb944b2412112d19155f1f4bbe1d190fc23e9ff9ea3584a8bf5505668c996a708f5a8dc8174080e4cbaa5c8dced9d53eda0ff4f1f114dd33c27f9f60e3f8
6
+ metadata.gz: 747343cd474efbbf2e881bf9921cc0b9c4166821a96f2fcf69edcc8effee88481b0f80bcfae9921b631fb66a72df39d2934e4f69424df7c2352d4f2faaf5a28f
7
+ data.tar.gz: 18b13644f200d75450d070b085a054d02da6aab70d51981cce43126371d50dfe2eefc2c42bf2caa70d9d878cdcc15e18f9337dc7d721d5f1b4c85b6bc0e1ba3e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.2] - 2025-01-19
4
+
5
+ ### Added
6
+ - Added `next_billing_at` field support to `Memberships.create` method for setting the next billing date
7
+
8
+ ## [0.3.1] - 2025-09-04
9
+
10
+ ### Added
11
+ - Added `tags` parameter support to `CalendarItems.create` method for categorizing calendar items
12
+ - Added `email` parameter to `Contacts.all` method for filtering contacts by email address
13
+
14
+ ### Changed
15
+ - **BREAKING**: Updated `Contacts.all` method to use keyword arguments (limit:, offset:, email:, config:) instead of positional arguments
16
+
17
+ ## [0.3.0] - 2025-07-27
18
+
19
+ ### Added
20
+ - Calendar Items API support with full CRUD operations:
21
+ - `create` - Create calendar events for contacts
22
+ - `update` - Update existing calendar items
23
+ - `find` - Retrieve a specific calendar item
24
+ - `delete` - Remove calendar items
25
+ - `all` - List calendar items with filtering and pagination support
26
+ - Support for calendar item metadata including description, location, external_id, external_data, and tags
27
+ - Comprehensive test coverage for Calendar Items functionality
28
+
3
29
  ## [0.2.0] - 2025-05-26
4
30
 
5
31
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- patch_retention (0.2.2)
4
+ patch_retention (0.3.1)
5
5
  faraday (~> 1.10)
6
6
  zeitwerk (~> 2.6)
7
7
 
data/README.md CHANGED
@@ -118,7 +118,21 @@ Then, you can use the gem's methods to interact with the API.
118
118
  To retrieve all contacts:
119
119
 
120
120
  ```ruby
121
+ # Basic usage
121
122
  contacts = PatchRetention::Contacts.all
123
+
124
+ # With pagination (using keyword arguments)
125
+ contacts = PatchRetention::Contacts.all(limit: 10, offset: 0)
126
+
127
+ # With email filter
128
+ contacts = PatchRetention::Contacts.all(email: 'john.doe@example.com')
129
+
130
+ # With pagination and email filter
131
+ contacts = PatchRetention::Contacts.all(
132
+ limit: 50,
133
+ offset: 0,
134
+ email: 'john@example.com'
135
+ )
122
136
  ```
123
137
 
124
138
  To retrieve a single contact:
@@ -264,6 +278,7 @@ membership = PatchRetention::Memberships.create(
264
278
  product_id: "65de5xxxxxxxxxxxxx", # Required, ID of the product (e.g., from product creation)
265
279
  start_at: Time.now.xmlschema, # Optional, ISO8601 timestamp
266
280
  end_at: (Time.now + 30*24*60*60).xmlschema, # Optional, ISO8601 timestamp (e.g., 30 days from now)
281
+ next_billing_at: (Time.now + 7*24*60*60).xmlschema, # Optional, ISO8601 timestamp for next billing date
267
282
  external_id: "MEM123", # Optional
268
283
  data: {
269
284
  "is_trial" => true,
@@ -290,6 +305,90 @@ To find a membership:
290
305
  membership = PatchRetention::Memberships.find(membership_id: "mem_xxxxxxxxxxxxxx")
291
306
  ```
292
307
 
308
+ **Calendar Items**
309
+
310
+ To create a calendar item:
311
+
312
+ ```ruby
313
+ calendar_item = PatchRetention::CalendarItems.create(
314
+ contact_id: "ct_xxxxxxxxxxxxxx", # Required, ID of the contact
315
+ title: "Tennis Court Reservation", # Required, title of the event
316
+ start_at: "2025-02-01T10:00:00Z", # Required, ISO8601 timestamp - when the event starts
317
+ end_at: "2025-02-01T11:00:00Z", # Required, ISO8601 timestamp - when the event ends
318
+ run_start_at: "2025-02-01T09:30:00Z", # Optional, ISO8601 - when to run the event for this item (defaults to start_at if not set)
319
+ run_end_at: "2025-02-01T11:30:00Z", # Optional, ISO8601 - when to run the event for this item (defaults to end_at if not set)
320
+ data: { # Optional, additional metadata that will be included in the calendar item
321
+ external_id: "res_123456", # Your system's ID
322
+ facility_id: "fac_789",
323
+ court_name: "Court 1",
324
+ reservation_type: "match"
325
+ },
326
+ tags: ["tennis", "premium", "court1"], # Optional, array of tags to categorize the calendar item
327
+ time_occurred: "2025-01-28T09:00:00Z", # Optional, ISO8601 - past or current time for the event (will default to now)
328
+ skip_triggers: false # Optional, if set to false or empty, any automation tied to the calendar item will not run
329
+ )
330
+ # => {"id"=>"cal_xxxxxxxxxxxxxx", "contact_id"=>"ct_xxxxxxxxxxxxxx", ...}
331
+ ```
332
+
333
+ To update a calendar item:
334
+
335
+ ```ruby
336
+ calendar_item = PatchRetention::CalendarItems.update(
337
+ calendar_item_id: "cal_xxxxxxxxxxxxxx",
338
+ title: "Updated Tennis Match",
339
+ end_at: "2025-02-01T12:00:00Z", # Extend by 1 hour
340
+ data: {
341
+ description: "Match extended due to tie-break"
342
+ },
343
+ tags: ["Tennis", "Extended", "Tie-break"] # Tags as separate parameter
344
+ )
345
+ ```
346
+
347
+ To find a calendar item:
348
+
349
+ ```ruby
350
+ calendar_item = PatchRetention::CalendarItems.find(calendar_item_id: "cal_xxxxxxxxxxxxxx")
351
+ ```
352
+
353
+ To delete a calendar item:
354
+
355
+ ```ruby
356
+ result = PatchRetention::CalendarItems.delete(calendar_item_id: "cal_xxxxxxxxxxxxxx")
357
+ # => { success: true }
358
+ ```
359
+
360
+ To list calendar items:
361
+
362
+ ```ruby
363
+ # List all calendar items
364
+ calendar_items = PatchRetention::CalendarItems.all()
365
+
366
+ # List calendar items for a specific contact
367
+ calendar_items = PatchRetention::CalendarItems.all(contact_id: "ct_xxxxxxxxxxxxxx")
368
+
369
+ # List calendar items within ID range (MongoDB IDs)
370
+ calendar_items = PatchRetention::CalendarItems.all(
371
+ min_id: "0123456789abcdefghijklmn", # Get all items on or after this ID
372
+ max_id: "0123456789abcdefghijklmn" # Get all items on or before this ID
373
+ )
374
+
375
+ # List specific calendar items by IDs (comma-separated)
376
+ calendar_items = PatchRetention::CalendarItems.all(
377
+ id: "0123456789abcdefghijklmn,123456789abcdefghijklmn"
378
+ )
379
+
380
+ # Filter by date range (predefined options)
381
+ calendar_items = PatchRetention::CalendarItems.all(
382
+ date_range: "Today" # Options: "Today", "Yesterday", "Last 7 Days", "This Week", "Last Week", "Last 30 Days"
383
+ )
384
+
385
+ # With pagination
386
+ calendar_items = PatchRetention::CalendarItems.all(
387
+ limit: 50, # Default is 50, max is 100
388
+ offset: 25 # Skip first 25 results
389
+ )
390
+ ```
391
+
293
392
  ## Development
294
393
 
295
394
  After checking out the repo, run `bin/setup` to install dependencies.
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PatchRetention
4
+ class CalendarItems
5
+ class << self
6
+ def create(contact_id:, title:, start_at:, end_at:, run_start_at: nil, run_end_at: nil,
7
+ data: nil, time_occurred: nil, skip_triggers: false, tags: nil, config: nil)
8
+ payload = {
9
+ contact_id: contact_id,
10
+ title: title,
11
+ start_at: start_at,
12
+ end_at: end_at,
13
+ }
14
+ payload[:run_start_at] = run_start_at if run_start_at
15
+ payload[:run_end_at] = run_end_at if run_end_at
16
+ payload[:data] = data if data
17
+ payload[:time_occurred] = time_occurred if time_occurred
18
+ payload[:skip_triggers] = skip_triggers unless skip_triggers.nil?
19
+ payload[:tags] = tags if tags
20
+
21
+ response = PatchRetention.connection(config).post("/v2/calendar_items") do |req|
22
+ req.body = payload.to_json
23
+ req.headers["Content-Type"] = "application/json"
24
+ end
25
+
26
+ JSON.parse(response.body)
27
+ rescue Faraday::Error => e
28
+ raise Error, "Failed to create calendar item: #{e.message}"
29
+ end
30
+
31
+ def update(calendar_item_id:, title: nil, start_at: nil, end_at: nil, run_start_at: nil,
32
+ run_end_at: nil, data: nil, tags: nil, config: nil)
33
+ payload = {}
34
+ payload[:title] = title if title
35
+ payload[:start_at] = start_at if start_at
36
+ payload[:end_at] = end_at if end_at
37
+ payload[:run_start_at] = run_start_at if run_start_at
38
+ payload[:run_end_at] = run_end_at if run_end_at
39
+ payload[:data] = data if data
40
+ payload[:tags] = tags if tags
41
+
42
+ response = PatchRetention.connection(config).patch("/v2/calendar_items/#{calendar_item_id}") do |req|
43
+ req.body = payload.to_json
44
+ req.headers["Content-Type"] = "application/json"
45
+ end
46
+
47
+ JSON.parse(response.body)
48
+ rescue Faraday::Error => e
49
+ raise Error, "Failed to update calendar item: #{e.message}"
50
+ end
51
+
52
+ def find(calendar_item_id:, config: nil)
53
+ response = PatchRetention.connection(config).get("/v2/calendar_items/#{calendar_item_id}")
54
+
55
+ JSON.parse(response.body)
56
+ rescue Faraday::Error => e
57
+ raise Error, "Failed to find calendar item: #{e.message}"
58
+ end
59
+
60
+ def delete(calendar_item_id:, config: nil)
61
+ response = PatchRetention.connection(config).delete("/v2/calendar_items/#{calendar_item_id}")
62
+
63
+ { success: response.status == 204 }
64
+ rescue Faraday::Error => e
65
+ raise Error, "Failed to delete calendar item: #{e.message}"
66
+ end
67
+
68
+ def all(contact_id: nil, min_id: nil, max_id: nil, id: nil, date_range: nil, limit: nil, offset: nil, config: nil)
69
+ params = {}
70
+ params[:contact_id] = contact_id if contact_id
71
+ params[:min_id] = min_id if min_id
72
+ params[:max_id] = max_id if max_id
73
+ params[:id] = id if id
74
+ params[:date_range] = date_range if date_range
75
+ params[:limit] = limit if limit
76
+ params[:offset] = offset if offset
77
+
78
+ response = PatchRetention.connection(config).get("/v2/calendar_items", params)
79
+
80
+ JSON.parse(response.body)
81
+ rescue Faraday::Error => e
82
+ raise Error, "Failed to retrieve calendar items: #{e.message}"
83
+ end
84
+ end
85
+ end
86
+ end
@@ -29,13 +29,16 @@ module PatchRetention::Contacts::Find
29
29
  #
30
30
  # @param limit [Integer] The number of contacts to retrieve per page.
31
31
  # @param offset [Integer] The number of contacts to skip before starting to collect the result set.
32
+ # @param email [String] Optional email to filter contacts by.
33
+ # @param config [Configuration] Optional configuration object.
32
34
  # @return [Object] The response from the PatchRetention API.
33
35
  # @raise [PatchRetention::Error] If the API returns a status other than 200.
34
- def all(limit, offset, config = nil)
36
+ def all(limit:, offset:, email: nil, config: nil)
35
37
  raise_error_if_present do
36
38
  PatchRetention.connection(config).get(PatchRetention::Contacts::API_PATH) do |req|
37
39
  req.params["limit"] = limit
38
40
  req.params["offset"] = offset
41
+ req.params["email"] = email if email
39
42
  end
40
43
  end
41
44
  end
@@ -8,8 +8,8 @@ class PatchRetention::Contacts
8
8
  Find.by_id(id, config)
9
9
  end
10
10
 
11
- def all(limit = 30, offset = 0, config = nil)
12
- Find.all(limit, offset, config)
11
+ def all(limit: 30, offset: 0, email: nil, config: nil)
12
+ Find.all(limit: limit, offset: offset, email: email, config: config)
13
13
  end
14
14
 
15
15
  def find_or_create_by(contact_params:, query_params: {}, config: nil)
@@ -3,14 +3,15 @@
3
3
  module PatchRetention
4
4
  class Memberships
5
5
  class << self
6
- def create(contact_id:, product_id:, start_at: nil, end_at: nil, external_id: nil, tags: nil, data: nil,
7
- config: nil)
6
+ def create(contact_id:, product_id:, start_at: nil, end_at: nil, next_billing_at: nil, external_id: nil,
7
+ tags: nil, data: nil, config: nil)
8
8
  payload = {
9
9
  contact_id: contact_id,
10
10
  product_id: product_id,
11
11
  }
12
12
  payload[:start_at] = start_at if start_at
13
13
  payload[:end_at] = end_at if end_at
14
+ payload[:next_billing_at] = next_billing_at if next_billing_at
14
15
  payload[:external_id] = external_id if external_id
15
16
  payload[:tags] = tags if tags
16
17
  payload[:data] = data if data
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PatchRetention
4
- VERSION = "0.2.2"
4
+ VERSION = "0.3.2"
5
5
  end
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: patch_retention
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Playbypoint
8
8
  - Gerardo Ortega
9
+ - Segundo Rebaza
9
10
  autorequire:
10
11
  bindir: exe
11
12
  cert_chain: []
12
- date: 2025-07-28 00:00:00.000000000 Z
13
+ date: 2025-09-19 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: faraday
@@ -67,20 +68,6 @@ dependencies:
67
68
  - - "~>"
68
69
  - !ruby/object:Gem::Version
69
70
  version: '0.9'
70
- - !ruby/object:Gem::Dependency
71
- name: thor
72
- requirement: !ruby/object:Gem::Requirement
73
- requirements:
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: 1.4.0
77
- type: :development
78
- prerelease: false
79
- version_requirements: !ruby/object:Gem::Requirement
80
- requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
83
- version: 1.4.0
84
71
  - !ruby/object:Gem::Dependency
85
72
  name: byebug
86
73
  requirement: !ruby/object:Gem::Requirement
@@ -179,6 +166,20 @@ dependencies:
179
166
  - - "~>"
180
167
  - !ruby/object:Gem::Version
181
168
  version: '2.15'
169
+ - !ruby/object:Gem::Dependency
170
+ name: thor
171
+ requirement: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: 1.4.0
176
+ type: :development
177
+ prerelease: false
178
+ version_requirements: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: 1.4.0
182
183
  - !ruby/object:Gem::Dependency
183
184
  name: vcr
184
185
  requirement: !ruby/object:Gem::Requirement
@@ -225,6 +226,7 @@ description: Patch Retention API wrapper.
225
226
  email:
226
227
  - webmaster@playbypoint.com
227
228
  - g3ortega@gmail.com
229
+ - alvaro.rp1593@gmail.com
228
230
  executables: []
229
231
  extensions: []
230
232
  extra_rdoc_files: []
@@ -251,6 +253,7 @@ files:
251
253
  - docs/references/troubleshooting.md
252
254
  - docs/wip/session-2025-05-26.md
253
255
  - lib/patch_retention.rb
256
+ - lib/patch_retention/calendar_items.rb
254
257
  - lib/patch_retention/configuration.rb
255
258
  - lib/patch_retention/contacts.rb
256
259
  - lib/patch_retention/contacts/delete.rb