supersaas-api-client 2.0.4 → 2.1.0
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 +4 -4
- data/README.md +129 -43
- data/examples/appointments.rb +16 -22
- data/examples/forms.rb +9 -5
- data/examples/groups.rb +2 -1
- data/examples/promotions.rb +5 -4
- data/examples/schedules.rb +7 -7
- data/examples/slots.rb +42 -0
- data/examples/users.rb +1 -1
- data/lib/supersaas-api-client/api/appointments.rb +38 -43
- data/lib/supersaas-api-client/api/base_api.rb +2 -0
- data/lib/supersaas-api-client/api/forms.rb +3 -1
- data/lib/supersaas-api-client/api/groups.rb +1 -1
- data/lib/supersaas-api-client/api/hooks.rb +25 -0
- data/lib/supersaas-api-client/api/promotions.rb +1 -1
- data/lib/supersaas-api-client/api/schedules.rb +9 -1
- data/lib/supersaas-api-client/api/slots.rb +63 -0
- data/lib/supersaas-api-client/api/users.rb +39 -41
- data/lib/supersaas-api-client/client.rb +48 -32
- data/lib/supersaas-api-client/exception.rb +8 -0
- data/lib/supersaas-api-client/models/appointment.rb +5 -4
- data/lib/supersaas-api-client/models/base_model.rb +18 -2
- data/lib/supersaas-api-client/models/field_list.rb +11 -2
- data/lib/supersaas-api-client/models/form.rb +1 -2
- data/lib/supersaas-api-client/models/slot.rb +1 -1
- data/lib/supersaas-api-client/models/user.rb +2 -0
- data/lib/supersaas-api-client/version.rb +1 -1
- data/lib/supersaas.rb +2 -0
- metadata +11 -17
- data/.github/workflows/actions.yaml +0 -21
- data/.gitignore +0 -13
- data/.rubocop.yml +0 -1
- data/.rubocop_todo.yml +0 -296
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -49
- data/Rakefile +0 -12
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/supersaas-api-client.gemspec +0 -28
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
module Supersaas
|
|
4
4
|
# REF: https://www.supersaas.com/info/dev/appointment_api
|
|
5
5
|
class Appointments < BaseApi
|
|
6
|
-
def agenda(schedule_id,
|
|
6
|
+
def agenda(schedule_id, user, from_time = nil, slot = false)
|
|
7
7
|
path = "/agenda/#{validate_id(schedule_id)}"
|
|
8
8
|
params = {
|
|
9
|
-
user: validate_present(
|
|
9
|
+
user: validate_present(user),
|
|
10
10
|
from: from_time && validate_datetime(from_time)
|
|
11
11
|
}
|
|
12
12
|
params.merge!(slot: true) if slot
|
|
@@ -14,6 +14,7 @@ module Supersaas
|
|
|
14
14
|
map_slots_or_bookings(res)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
# LEGACY METHOD WILL BE REMOVED USE AGENDA
|
|
17
18
|
def agenda_slots(schedule_id, user_id, from_time = nil)
|
|
18
19
|
path = "/agenda/#{validate_id(schedule_id)}"
|
|
19
20
|
params = {
|
|
@@ -38,14 +39,16 @@ module Supersaas
|
|
|
38
39
|
map_slots_or_bookings(res)
|
|
39
40
|
end
|
|
40
41
|
|
|
41
|
-
def list(schedule_id, form = nil, start_time = nil, limit = nil)
|
|
42
|
+
def list(schedule_id, form = nil, start_time = nil, limit = nil, finish = nil, offset = nil)
|
|
42
43
|
path = '/bookings'
|
|
43
44
|
params = {
|
|
44
45
|
schedule_id: validate_id(schedule_id),
|
|
45
46
|
form: form ? true : nil,
|
|
46
|
-
start: start_time ? validate_datetime(start_time) : nil
|
|
47
|
+
start: start_time ? validate_datetime(start_time) : nil,
|
|
48
|
+
finish: finish ? validate_datetime(finish) : nil
|
|
47
49
|
}
|
|
48
50
|
params.merge!(limit: validate_number(limit)) if limit
|
|
51
|
+
params.merge!(offset: validate_number(offset)) if offset
|
|
49
52
|
res = client.get(path, params)
|
|
50
53
|
map_slots_or_bookings(res)
|
|
51
54
|
end
|
|
@@ -64,24 +67,7 @@ module Supersaas
|
|
|
64
67
|
webhook: webhook,
|
|
65
68
|
user_id: validate_id(user_id),
|
|
66
69
|
form: form ? true : nil,
|
|
67
|
-
booking:
|
|
68
|
-
start: attributes[:start],
|
|
69
|
-
finish: attributes[:finish],
|
|
70
|
-
name: attributes[:name],
|
|
71
|
-
email: attributes[:email],
|
|
72
|
-
full_name: attributes[:full_name],
|
|
73
|
-
address: attributes[:address],
|
|
74
|
-
mobile: attributes[:mobile],
|
|
75
|
-
phone: attributes[:phone],
|
|
76
|
-
country: attributes[:country],
|
|
77
|
-
field_1: attributes[:field_1],
|
|
78
|
-
field_2: attributes[:field_2],
|
|
79
|
-
field_1_r: attributes[:field_1_r],
|
|
80
|
-
field_2_r: attributes[:field_2_r],
|
|
81
|
-
super_field: attributes[:super_field],
|
|
82
|
-
resource_id: attributes[:resource_id],
|
|
83
|
-
slot_id: attributes[:slot_id]
|
|
84
|
-
}
|
|
70
|
+
booking: booking_params(attributes)
|
|
85
71
|
}
|
|
86
72
|
params[:booking].compact!
|
|
87
73
|
client.post(path, params)
|
|
@@ -91,24 +77,7 @@ module Supersaas
|
|
|
91
77
|
path = "/bookings/#{validate_id(appointment_id)}"
|
|
92
78
|
params = {
|
|
93
79
|
schedule_id: schedule_id,
|
|
94
|
-
booking:
|
|
95
|
-
start: attributes[:start],
|
|
96
|
-
finish: attributes[:finish],
|
|
97
|
-
name: attributes[:name],
|
|
98
|
-
email: attributes[:email],
|
|
99
|
-
full_name: attributes[:full_name],
|
|
100
|
-
address: attributes[:address],
|
|
101
|
-
mobile: attributes[:mobile],
|
|
102
|
-
phone: attributes[:phone],
|
|
103
|
-
country: attributes[:country],
|
|
104
|
-
field_1: attributes[:field_1],
|
|
105
|
-
field_2: attributes[:field_2],
|
|
106
|
-
field_1_r: attributes[:field_1_r],
|
|
107
|
-
field_2_r: attributes[:field_2_r],
|
|
108
|
-
super_field: attributes[:super_field],
|
|
109
|
-
resource_id: attributes[:resource_id],
|
|
110
|
-
slot_id: attributes[:slot_id]
|
|
111
|
-
}
|
|
80
|
+
booking: booking_params(attributes)
|
|
112
81
|
}
|
|
113
82
|
|
|
114
83
|
params.merge!(form: form) if form
|
|
@@ -117,9 +86,10 @@ module Supersaas
|
|
|
117
86
|
client.put(path, params)
|
|
118
87
|
end
|
|
119
88
|
|
|
120
|
-
def delete(schedule_id, appointment_id)
|
|
89
|
+
def delete(schedule_id, appointment_id, webhook = nil)
|
|
121
90
|
path = "/bookings/#{validate_id(appointment_id)}"
|
|
122
91
|
params = { schedule_id: validate_id(schedule_id) }
|
|
92
|
+
params.merge!(webhook: webhook) if webhook
|
|
123
93
|
client.delete(path, nil, params)
|
|
124
94
|
end
|
|
125
95
|
|
|
@@ -130,8 +100,8 @@ module Supersaas
|
|
|
130
100
|
map_slots_or_bookings(res)
|
|
131
101
|
end
|
|
132
102
|
|
|
133
|
-
def range(schedule_id, today = false, from_time = nil, to = nil, slot = false, user = nil, resource_id = nil,
|
|
134
|
-
limit = nil, offset = nil)
|
|
103
|
+
def range(schedule_id, today = false, from_time = nil, to = nil, slot = false, user = nil, resource_id = nil,
|
|
104
|
+
service_id = nil, limit = nil, offset = nil)
|
|
135
105
|
path = "/range/#{validate_id(schedule_id)}"
|
|
136
106
|
params = {}
|
|
137
107
|
params = build_param(params, from_time, to, slot, user, limit, offset, resource_id, service_id)
|
|
@@ -142,6 +112,31 @@ module Supersaas
|
|
|
142
112
|
|
|
143
113
|
private
|
|
144
114
|
|
|
115
|
+
# Input attributes only. description is for resource schedules, quantity (number of places) for capacity schedules, form_id attaches an existing form
|
|
116
|
+
def booking_params(attributes)
|
|
117
|
+
{
|
|
118
|
+
start: attributes[:start],
|
|
119
|
+
finish: attributes[:finish],
|
|
120
|
+
email: attributes[:email],
|
|
121
|
+
res_name: attributes[:name],
|
|
122
|
+
full_name: attributes[:full_name],
|
|
123
|
+
address: attributes[:address],
|
|
124
|
+
mobile: attributes[:mobile],
|
|
125
|
+
phone: attributes[:phone],
|
|
126
|
+
country: attributes[:country],
|
|
127
|
+
field_1: attributes[:field_1],
|
|
128
|
+
field_2: attributes[:field_2],
|
|
129
|
+
field_1_r: attributes[:field_1_r],
|
|
130
|
+
field_2_r: attributes[:field_2_r],
|
|
131
|
+
super_field: attributes[:super_field],
|
|
132
|
+
resource_id: attributes[:resource_id],
|
|
133
|
+
slot_id: attributes[:slot_id],
|
|
134
|
+
description: attributes[:description],
|
|
135
|
+
quantity: attributes[:quantity],
|
|
136
|
+
form_id: attributes[:form_id]
|
|
137
|
+
}
|
|
138
|
+
end
|
|
139
|
+
|
|
145
140
|
def map_slots_or_bookings(obj, slot = false)
|
|
146
141
|
if obj.is_a?(Array) && slot
|
|
147
142
|
obj.map { |attributes| Supersaas::Slot.new(attributes) }
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
module Supersaas
|
|
4
4
|
# REF: https://www.supersaas.com/info/dev/form_api
|
|
5
5
|
class Forms < BaseApi
|
|
6
|
-
def list(template_form_id, from_time = nil, user = nil)
|
|
6
|
+
def list(template_form_id, from_time = nil, user = nil, limit = nil, offset = nil)
|
|
7
7
|
path = '/forms'
|
|
8
8
|
params = { form_id: validate_id(template_form_id) }
|
|
9
9
|
params.merge!(from: validate_datetime(from_time)) if from_time
|
|
10
10
|
params.merge!(user: validate_user(user)) if user
|
|
11
|
+
params.merge!(limit: limit) if limit
|
|
12
|
+
params.merge!(offset: offset) if offset
|
|
11
13
|
res = client.get(path, params)
|
|
12
14
|
res.map { |attributes| Supersaas::Form.new(attributes) }
|
|
13
15
|
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Supersaas
|
|
4
|
+
# REF: https://www.supersaas.com/info/dev/information_api#groups
|
|
4
5
|
class Groups < BaseApi
|
|
5
|
-
# REF: https://www.supersaas.com/info/dev/information_api#groups
|
|
6
6
|
def list
|
|
7
7
|
path = '/groups'
|
|
8
8
|
res = client.get(path)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Supersaas
|
|
4
|
+
# REF: https://www.supersaas.com/info/dev/webhooks
|
|
5
|
+
class Hooks < BaseApi
|
|
6
|
+
# event: the trigger, e.g. 'U' (user created), 'M' (user changed), 'N' (new appointment), 'C' (changed appointment)
|
|
7
|
+
# parent_id: the schedule id for appointment events, the super form id for form events, else the account id
|
|
8
|
+
# Returns { 'id' => ..., 'parent_id' => ... }
|
|
9
|
+
def create(target_url, event, parent_id)
|
|
10
|
+
path = '/hooks'
|
|
11
|
+
params = {
|
|
12
|
+
target_url: validate_present(target_url),
|
|
13
|
+
event: validate_present(event),
|
|
14
|
+
parent_id: validate_id(parent_id)
|
|
15
|
+
}
|
|
16
|
+
client.post(path, params)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def delete(hook_id, parent_id)
|
|
20
|
+
path = '/hooks'
|
|
21
|
+
query = { id: validate_id(hook_id), parent_id: validate_id(parent_id) }
|
|
22
|
+
client.delete(path, nil, query)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Supersaas
|
|
4
|
+
# REF: https://www.supersaas.com/info/dev/promotion_api
|
|
4
5
|
class Promotions < BaseApi
|
|
5
|
-
# REF: https://www.supersaas.com/info/dev/promotion_api
|
|
6
6
|
def list(limit = nil, offset = nil)
|
|
7
7
|
path = '/promotions'
|
|
8
8
|
params = {}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Supersaas
|
|
4
|
+
# REF: https://www.supersaas.com/info/dev/information_api
|
|
4
5
|
class Schedules < BaseApi
|
|
5
|
-
# REF: https://www.supersaas.com/info/dev/information_api
|
|
6
6
|
def list
|
|
7
7
|
path = '/schedules'
|
|
8
8
|
res = client.get(path)
|
|
@@ -22,5 +22,13 @@ module Supersaas
|
|
|
22
22
|
res = client.get(path, query)
|
|
23
23
|
res.map { |attributes| Supersaas::FieldList.new(attributes) }
|
|
24
24
|
end
|
|
25
|
+
|
|
26
|
+
# The fields that can be set when creating a booking
|
|
27
|
+
def input_field_list(schedule_id)
|
|
28
|
+
path = '/input_field_list'
|
|
29
|
+
query = { schedule_id: validate_id(schedule_id) }
|
|
30
|
+
res = client.get(path, query)
|
|
31
|
+
res.map { |attributes| Supersaas::FieldList.new(attributes) }
|
|
32
|
+
end
|
|
25
33
|
end
|
|
26
34
|
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Supersaas
|
|
4
|
+
# REF: https://www.supersaas.com/info/dev/appointment_api#slots_api
|
|
5
|
+
# Only available for capacity type schedules.
|
|
6
|
+
class Slots < BaseApi
|
|
7
|
+
def list(schedule_id, start_time = nil, finish = nil, limit = nil, offset = nil)
|
|
8
|
+
path = '/slots'
|
|
9
|
+
params = {
|
|
10
|
+
schedule_id: validate_id(schedule_id),
|
|
11
|
+
start: start_time ? validate_datetime(start_time) : nil,
|
|
12
|
+
finish: finish ? validate_datetime(finish) : nil
|
|
13
|
+
}
|
|
14
|
+
params.merge!(limit: validate_number(limit)) if limit
|
|
15
|
+
params.merge!(offset: validate_number(offset)) if offset
|
|
16
|
+
res = client.get(path, params)
|
|
17
|
+
res.map { |attributes| Supersaas::Slot.new(attributes) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def get(schedule_id, slot_id)
|
|
21
|
+
params = { schedule_id: validate_id(schedule_id) }
|
|
22
|
+
path = "/slots/#{validate_id(slot_id)}"
|
|
23
|
+
res = client.get(path, params)
|
|
24
|
+
Supersaas::Slot.new(res)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def create(schedule_id, attributes)
|
|
28
|
+
path = '/slots'
|
|
29
|
+
query = { schedule_id: validate_id(schedule_id) }
|
|
30
|
+
client.post(path, { slot: slot_params(attributes) }, query)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def update(schedule_id, slot_id, attributes)
|
|
34
|
+
path = "/slots/#{validate_id(slot_id)}"
|
|
35
|
+
query = { schedule_id: validate_id(schedule_id) }
|
|
36
|
+
client.put(path, { slot: slot_params(attributes) }, query)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete(schedule_id, slot_id)
|
|
40
|
+
path = "/slots/#{validate_id(slot_id)}"
|
|
41
|
+
params = { schedule_id: validate_id(schedule_id) }
|
|
42
|
+
client.delete(path, nil, params)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# capacity: an Integer, or '-' for unlimited, '0' for no places
|
|
48
|
+
def slot_params(attributes)
|
|
49
|
+
params = {
|
|
50
|
+
start: attributes[:start] && validate_datetime(attributes[:start]),
|
|
51
|
+
finish: attributes[:finish] && validate_datetime(attributes[:finish]),
|
|
52
|
+
title: attributes[:title],
|
|
53
|
+
description: attributes[:description],
|
|
54
|
+
location: attributes[:location],
|
|
55
|
+
capacity: attributes[:capacity],
|
|
56
|
+
price: attributes[:price],
|
|
57
|
+
color: attributes[:color]
|
|
58
|
+
}
|
|
59
|
+
params.compact!
|
|
60
|
+
params
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -10,13 +10,17 @@ module Supersaas
|
|
|
10
10
|
limit: limit && validate_number(limit),
|
|
11
11
|
offset: offset && validate_number(offset)
|
|
12
12
|
}
|
|
13
|
+
params.compact!
|
|
13
14
|
res = client.get(path, params)
|
|
14
15
|
res.map { |attributes| Supersaas::User.new(attributes) }
|
|
15
16
|
end
|
|
16
17
|
|
|
17
|
-
def get(user_id)
|
|
18
|
+
def get(user_id, form = nil)
|
|
18
19
|
path = user_path(user_id)
|
|
19
|
-
|
|
20
|
+
params = {
|
|
21
|
+
form: form ? true : nil
|
|
22
|
+
}
|
|
23
|
+
res = client.get(path, params)
|
|
20
24
|
Supersaas::User.new(res)
|
|
21
25
|
end
|
|
22
26
|
|
|
@@ -24,24 +28,7 @@ module Supersaas
|
|
|
24
28
|
path = user_path(user_id)
|
|
25
29
|
query = { webhook: webhook }
|
|
26
30
|
query.merge!(duplicate: validate_duplicate(duplicate)) if duplicate
|
|
27
|
-
params = {
|
|
28
|
-
user: {
|
|
29
|
-
name: validate_name(attributes[:name]),
|
|
30
|
-
email: attributes[:email],
|
|
31
|
-
password: attributes[:password],
|
|
32
|
-
full_name: attributes[:full_name],
|
|
33
|
-
address: attributes[:address],
|
|
34
|
-
mobile: attributes[:mobile],
|
|
35
|
-
phone: attributes[:phone],
|
|
36
|
-
country: attributes[:country],
|
|
37
|
-
timezone: attributes[:timezone],
|
|
38
|
-
field_1: attributes[:field_1],
|
|
39
|
-
field_2: attributes[:field_2],
|
|
40
|
-
super_field: attributes[:super_field],
|
|
41
|
-
credit: attributes[:credit] && validate_number(attributes[:credit]),
|
|
42
|
-
role: attributes[:role] && validate_options(attributes[:role], User::ROLES)
|
|
43
|
-
}
|
|
44
|
-
}
|
|
31
|
+
params = { user: user_params(attributes) }
|
|
45
32
|
client.post(path, params, query)
|
|
46
33
|
end
|
|
47
34
|
|
|
@@ -49,31 +36,14 @@ module Supersaas
|
|
|
49
36
|
path = user_path(user_id)
|
|
50
37
|
query = { webhook: webhook }
|
|
51
38
|
query.merge!(notfound: validate_notfound(notfound)) if notfound
|
|
52
|
-
params = {
|
|
53
|
-
user: {
|
|
54
|
-
name: validate_name(attributes[:name]),
|
|
55
|
-
email: attributes[:email],
|
|
56
|
-
password: attributes[:password],
|
|
57
|
-
full_name: attributes[:full_name],
|
|
58
|
-
address: attributes[:address],
|
|
59
|
-
mobile: attributes[:mobile],
|
|
60
|
-
phone: attributes[:phone],
|
|
61
|
-
country: attributes[:country],
|
|
62
|
-
timezone: attributes[:timezone],
|
|
63
|
-
field_1: attributes[:field_1],
|
|
64
|
-
field_2: attributes[:field_2],
|
|
65
|
-
super_field: attributes[:super_field],
|
|
66
|
-
credit: attributes[:credit] && validate_number(attributes[:credit]),
|
|
67
|
-
role: attributes[:role] && validate_options(attributes[:role], User::ROLES)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
params[:user].compact!
|
|
39
|
+
params = { user: user_params(attributes) }
|
|
71
40
|
client.put(path, params, query)
|
|
72
41
|
end
|
|
73
42
|
|
|
74
|
-
def delete(user_id)
|
|
43
|
+
def delete(user_id, webhook = nil)
|
|
75
44
|
path = user_path(user_id)
|
|
76
|
-
|
|
45
|
+
params = { webhook: webhook }
|
|
46
|
+
client.delete(path, nil, params)
|
|
77
47
|
end
|
|
78
48
|
|
|
79
49
|
def field_list
|
|
@@ -82,6 +52,13 @@ module Supersaas
|
|
|
82
52
|
res.map { |attributes| Supersaas::FieldList.new(attributes) }
|
|
83
53
|
end
|
|
84
54
|
|
|
55
|
+
# The fields that can be set when creating a user
|
|
56
|
+
def input_field_list
|
|
57
|
+
path = '/input_field_list'
|
|
58
|
+
res = client.get(path)
|
|
59
|
+
res.map { |attributes| Supersaas::FieldList.new(attributes) }
|
|
60
|
+
end
|
|
61
|
+
|
|
85
62
|
private
|
|
86
63
|
|
|
87
64
|
def user_path(user_id)
|
|
@@ -91,5 +68,26 @@ module Supersaas
|
|
|
91
68
|
"/users/#{validate_user(user_id)}"
|
|
92
69
|
end
|
|
93
70
|
end
|
|
71
|
+
|
|
72
|
+
# The user attributes the API accepts, leaving out the ones that are nil
|
|
73
|
+
def user_params(attributes)
|
|
74
|
+
{
|
|
75
|
+
name: validate_name(attributes[:name]),
|
|
76
|
+
email: attributes[:email],
|
|
77
|
+
password: attributes[:password],
|
|
78
|
+
full_name: attributes[:full_name],
|
|
79
|
+
address: attributes[:address],
|
|
80
|
+
mobile: attributes[:mobile],
|
|
81
|
+
phone: attributes[:phone],
|
|
82
|
+
country: attributes[:country],
|
|
83
|
+
timezone: attributes[:timezone],
|
|
84
|
+
field_1: attributes[:field_1],
|
|
85
|
+
field_2: attributes[:field_2],
|
|
86
|
+
super_field: attributes[:super_field],
|
|
87
|
+
credit: attributes[:credit] && validate_number(attributes[:credit]),
|
|
88
|
+
role: attributes[:role] && validate_options(attributes[:role], User::ROLES),
|
|
89
|
+
group: attributes[:group] && validate_number(attributes[:group])
|
|
90
|
+
}.compact
|
|
91
|
+
end
|
|
94
92
|
end
|
|
95
93
|
end
|
|
@@ -47,6 +47,10 @@ module Supersaas
|
|
|
47
47
|
@schedules ||= Schedules.new(self)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
def slots
|
|
51
|
+
@slots ||= Slots.new(self)
|
|
52
|
+
end
|
|
53
|
+
|
|
50
54
|
def users
|
|
51
55
|
@users ||= Users.new(self)
|
|
52
56
|
end
|
|
@@ -59,6 +63,16 @@ module Supersaas
|
|
|
59
63
|
@groups ||= Groups.new(self)
|
|
60
64
|
end
|
|
61
65
|
|
|
66
|
+
def hooks
|
|
67
|
+
@hooks ||= Hooks.new(self)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Checks the credentials, returns true or raises Supersaas::Exception
|
|
71
|
+
def ping
|
|
72
|
+
get('/ping')
|
|
73
|
+
true
|
|
74
|
+
end
|
|
75
|
+
|
|
62
76
|
def get(path, query = {})
|
|
63
77
|
request(:get, path, {}, query)
|
|
64
78
|
end
|
|
@@ -77,12 +91,14 @@ module Supersaas
|
|
|
77
91
|
|
|
78
92
|
private
|
|
79
93
|
|
|
80
|
-
# The rate limiter allows
|
|
94
|
+
# The rate limiter allows at most MAX_REQUESTS requests per WINDOW_SIZE seconds
|
|
81
95
|
WINDOW_SIZE = 1 # seconds
|
|
82
|
-
|
|
96
|
+
MAX_REQUESTS = 4
|
|
97
|
+
|
|
83
98
|
def throttle
|
|
84
99
|
# A queue to store timestamps of requests made within the rate limiting window
|
|
85
|
-
@queue ||= Array.new(
|
|
100
|
+
@queue ||= Array.new(MAX_REQUESTS)
|
|
101
|
+
|
|
86
102
|
# Represents the timestamp of the oldest request within the time window
|
|
87
103
|
oldest_request = @queue.push(Time.now).shift
|
|
88
104
|
# This ensures that the client does not make requests faster than the defined rate limit
|
|
@@ -136,7 +152,7 @@ module Supersaas
|
|
|
136
152
|
if verbose
|
|
137
153
|
puts '### SuperSaaS Client Request:'
|
|
138
154
|
puts "#{http_method} #{path}"
|
|
139
|
-
puts params.to_json
|
|
155
|
+
puts filter_secrets(params).to_json
|
|
140
156
|
puts '------------------------------'
|
|
141
157
|
end
|
|
142
158
|
|
|
@@ -159,6 +175,8 @@ module Supersaas
|
|
|
159
175
|
|
|
160
176
|
code = res.code.to_i
|
|
161
177
|
case code
|
|
178
|
+
when 204
|
|
179
|
+
{}
|
|
162
180
|
when 200, 201
|
|
163
181
|
if http_method == :post && res['location'] =~ /www.supersaas.com/
|
|
164
182
|
res['location']
|
|
@@ -171,34 +189,24 @@ module Supersaas
|
|
|
171
189
|
end
|
|
172
190
|
|
|
173
191
|
def handle_errors(code, res)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def print_errors(res)
|
|
196
|
-
json_body = json_body(res)
|
|
197
|
-
return unless json_body[:errors]
|
|
198
|
-
|
|
199
|
-
errors each do |error|
|
|
200
|
-
puts "Error code: #{error['code']}, #{error['title']}"
|
|
201
|
-
end
|
|
192
|
+
message = case code
|
|
193
|
+
when 422 then 'HTTP Request Error: Unprocessable Content'
|
|
194
|
+
when 400 then 'HTTP Request Error: Bad Request'
|
|
195
|
+
when 401 then 'HTTP Request Error: Unauthorised'
|
|
196
|
+
when 404 then 'HTTP Request Error: Not Found'
|
|
197
|
+
when 501 then 'Not yet implemented for service type schedule'
|
|
198
|
+
when 403 then 'Unauthorized'
|
|
199
|
+
when 405 then 'Not available for this schedule type'
|
|
200
|
+
else "HTTP Request Error: #{code}"
|
|
201
|
+
end
|
|
202
|
+
raise Supersaas::Exception.new(message, status: code, errors: parsed_errors(res))
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# The errors array of a JSON error body like {"errors":[{"status":"404","title":"Not found"}]}
|
|
206
|
+
def parsed_errors(res)
|
|
207
|
+
body = json_body(res)
|
|
208
|
+
errors = body['errors'] if body.is_a?(Hash)
|
|
209
|
+
errors.is_a?(Array) ? errors : []
|
|
202
210
|
end
|
|
203
211
|
|
|
204
212
|
def json_body(res)
|
|
@@ -216,6 +224,14 @@ module Supersaas
|
|
|
216
224
|
end
|
|
217
225
|
end
|
|
218
226
|
|
|
227
|
+
# A copy of the params with password values replaced, for verbose output only
|
|
228
|
+
def filter_secrets(value)
|
|
229
|
+
return value.map { |v| filter_secrets(v) } if value.is_a?(Array)
|
|
230
|
+
return value unless value.is_a?(Hash)
|
|
231
|
+
|
|
232
|
+
value.each_with_object({}) { |(k, v), h| h[k] = k.to_s == 'password' ? '[FILTERED]' : filter_secrets(v) }
|
|
233
|
+
end
|
|
234
|
+
|
|
219
235
|
class Configuration
|
|
220
236
|
DEFAULT_HOST = 'https://www.supersaas.com'
|
|
221
237
|
|
|
@@ -6,5 +6,13 @@ module Supersaas
|
|
|
6
6
|
@code = nil
|
|
7
7
|
|
|
8
8
|
attr_accessor :field, :code
|
|
9
|
+
# HTTP status code and the server's parsed errors, e.g. [{"status"=>"404", "title"=>"Not found"}]
|
|
10
|
+
attr_reader :status, :errors
|
|
11
|
+
|
|
12
|
+
def initialize(message = nil, status: nil, errors: [])
|
|
13
|
+
super(message)
|
|
14
|
+
@status = status
|
|
15
|
+
@errors = errors
|
|
16
|
+
end
|
|
9
17
|
end
|
|
10
18
|
end
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
module Supersaas
|
|
4
4
|
class Appointment < BaseModel
|
|
5
|
-
attr_accessor :
|
|
6
|
-
:
|
|
7
|
-
:
|
|
8
|
-
:
|
|
5
|
+
attr_accessor :field_1, :field_2, :field_2_r, :field_1_r, :country, :address, :mobile, :phone, :email, :price_cents,
|
|
6
|
+
:finish, :start, :service_name, :res_name, :id, :quantity, :status_message, :deleted,
|
|
7
|
+
:created_on, :slot_id, :created_by, :price, :status, :full_name, :super_field, :updated_by, :form_id,
|
|
8
|
+
:updated_on, :user_id, :waitlisted, :resource_id, :schedule_name, :schedule_id, :service_id
|
|
9
|
+
|
|
9
10
|
attr_reader :form, :slot
|
|
10
11
|
|
|
11
12
|
def form=(value)
|
|
@@ -10,12 +10,28 @@ module Supersaas
|
|
|
10
10
|
assign_attributes(attributes)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
# Hash-style access to the raw attribute value, with a String or Symbol key.
|
|
14
|
+
# Keeps code working that read nested data as a Hash, e.g. appointment.form['content'].
|
|
15
|
+
def [](key)
|
|
16
|
+
return attributes[key] if attributes.key?(key)
|
|
17
|
+
|
|
18
|
+
case key
|
|
19
|
+
when Symbol then attributes[key.to_s]
|
|
20
|
+
when String then attributes[key.to_sym]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_h
|
|
25
|
+
attributes.to_h
|
|
26
|
+
end
|
|
27
|
+
|
|
13
28
|
private
|
|
14
29
|
|
|
15
30
|
def assign_attributes(attributes)
|
|
16
31
|
attributes.each do |key, value|
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
# Keep custom writers such as Appointment#form=, which wrap nested data in models
|
|
33
|
+
self.class.module_eval { attr_accessor key } unless self.class.method_defined?("#{key}=")
|
|
34
|
+
public_send("#{key}=", value)
|
|
19
35
|
end
|
|
20
36
|
end
|
|
21
37
|
end
|
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
module Supersaas
|
|
4
4
|
class FieldList < BaseModel
|
|
5
|
-
attr_accessor :name, :type, :label, :advanced
|
|
5
|
+
attr_accessor :name, :type, :label, :advanced, :required
|
|
6
6
|
attr_reader :spec
|
|
7
7
|
|
|
8
8
|
def spec=(value)
|
|
9
|
-
@spec = value.is_a?(Array) ? value.map { |
|
|
9
|
+
@spec = value.is_a?(Array) ? value.map { |item| parse_spec_item(item) } : value
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
# Items arrive as JSON strings; anything else (or invalid JSON) is kept as is
|
|
15
|
+
def parse_spec_item(item)
|
|
16
|
+
item.is_a?(String) ? JSON.parse(item) : item
|
|
17
|
+
rescue JSON::ParserError
|
|
18
|
+
item
|
|
10
19
|
end
|
|
11
20
|
end
|
|
12
21
|
end
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Supersaas
|
|
4
4
|
class Form < BaseModel
|
|
5
|
-
attr_accessor :content, :created_on, :deleted, :id, :reservation_process_id, :super_form_id, :
|
|
6
|
-
:updated_on, :user_id
|
|
5
|
+
attr_accessor :content, :created_on, :deleted, :id, :reservation_process_id, :super_form_id, :updated_on, :user_id
|
|
7
6
|
end
|
|
8
7
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Supersaas
|
|
4
4
|
class Slot < BaseModel
|
|
5
|
-
attr_accessor :count, :description, :finish, :id, :location, :name, :start, :title
|
|
5
|
+
attr_accessor :capacity, :color, :count, :description, :finish, :id, :location, :name, :price, :start, :title
|
|
6
6
|
attr_reader :bookings
|
|
7
7
|
|
|
8
8
|
def bookings=(value)
|
|
@@ -5,6 +5,8 @@ module Supersaas
|
|
|
5
5
|
ROLES = [3, 4, -1].freeze
|
|
6
6
|
|
|
7
7
|
attr_reader :form
|
|
8
|
+
attr_accessor :name, :email, :password, :full_name, :address, :mobile, :phone, :country, :timezone, :field_1,
|
|
9
|
+
:field_2, :super_field, :credit, :role, :group, :webhook, :id, :fk, :created_on, :updated_on
|
|
8
10
|
|
|
9
11
|
def form=(value)
|
|
10
12
|
@form = value.is_a?(Hash) ? Supersaas::Form.new(value) : value
|