booker_ruby 1.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/lib/booker/booker.rb +5 -0
  3. data/lib/booker/business_client.rb +32 -0
  4. data/lib/booker/business_rest.rb +89 -0
  5. data/lib/booker/client.rb +182 -0
  6. data/lib/booker/common_rest.rb +38 -0
  7. data/lib/booker/customer_client.rb +31 -0
  8. data/lib/booker/customer_rest.rb +43 -0
  9. data/lib/booker/errors.rb +19 -0
  10. data/lib/booker/generic_token_store.rb +25 -0
  11. data/lib/booker/models/address.rb +12 -0
  12. data/lib/booker/models/appointment.rb +77 -0
  13. data/lib/booker/models/appointment_treatment.rb +51 -0
  14. data/lib/booker/models/available_time.rb +13 -0
  15. data/lib/booker/models/business_type.rb +5 -0
  16. data/lib/booker/models/category.rb +5 -0
  17. data/lib/booker/models/class_instance.rb +25 -0
  18. data/lib/booker/models/country.rb +5 -0
  19. data/lib/booker/models/current_price.rb +5 -0
  20. data/lib/booker/models/customer.rb +51 -0
  21. data/lib/booker/models/customer_2.rb +5 -0
  22. data/lib/booker/models/customer_record_type.rb +5 -0
  23. data/lib/booker/models/discount.rb +5 -0
  24. data/lib/booker/models/dynamic_price.rb +11 -0
  25. data/lib/booker/models/employee.rb +10 -0
  26. data/lib/booker/models/final_total.rb +5 -0
  27. data/lib/booker/models/gender.rb +5 -0
  28. data/lib/booker/models/location.rb +18 -0
  29. data/lib/booker/models/model.rb +123 -0
  30. data/lib/booker/models/online_booking_settings.rb +23 -0
  31. data/lib/booker/models/original_price.rb +5 -0
  32. data/lib/booker/models/payment_method.rb +5 -0
  33. data/lib/booker/models/preferred_staff_gender.rb +5 -0
  34. data/lib/booker/models/price.rb +8 -0
  35. data/lib/booker/models/receipt_display_price.rb +5 -0
  36. data/lib/booker/models/room.rb +12 -0
  37. data/lib/booker/models/shipping_address.rb +5 -0
  38. data/lib/booker/models/source.rb +5 -0
  39. data/lib/booker/models/spa.rb +5 -0
  40. data/lib/booker/models/spa_employee_availability_search_item.rb +11 -0
  41. data/lib/booker/models/status.rb +5 -0
  42. data/lib/booker/models/sub_category.rb +5 -0
  43. data/lib/booker/models/tag_price.rb +5 -0
  44. data/lib/booker/models/teacher.rb +5 -0
  45. data/lib/booker/models/teacher_2.rb +5 -0
  46. data/lib/booker/models/time_zone.rb +8 -0
  47. data/lib/booker/models/treatment.rb +19 -0
  48. data/lib/booker/models/type.rb +8 -0
  49. data/lib/booker/models/user.rb +73 -0
  50. data/lib/booker/version.rb +3 -0
  51. data/lib/booker_ruby.rb +86 -0
  52. metadata +192 -0
@@ -0,0 +1,25 @@
1
+ module Booker
2
+ class GenericTokenStore
3
+ def self.temp_access_token
4
+ @temp_access_token
5
+ end
6
+
7
+ def self.temp_access_token=(token)
8
+ @temp_access_token = token
9
+ end
10
+
11
+ def self.temp_access_token_expires_at
12
+ @temp_access_token_expires_at
13
+ end
14
+
15
+ def self.temp_access_token_expires_at=(expires_at)
16
+ @temp_access_token_expires_at = expires_at
17
+ end
18
+
19
+ def self.update_booker_access_token!(token, expires_at)
20
+ self.temp_access_token = token
21
+ self.temp_access_token_expires_at = expires_at
22
+ true
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ module Booker
2
+ module Models
3
+ class Address < Model
4
+ attr_accessor 'Street1',
5
+ 'Street2',
6
+ 'City',
7
+ 'State',
8
+ 'Zip',
9
+ 'Country'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,77 @@
1
+ module Booker
2
+ module Models
3
+ class Appointment < Model
4
+ attr_accessor 'BookingNumber',
5
+ 'Confirmable',
6
+ 'EndDateTime',
7
+ 'FinalTotal',
8
+ 'ID',
9
+ 'IsCancelled',
10
+ 'IsNoShow',
11
+ 'LocationID',
12
+ 'StartDateTime',
13
+ 'Status',
14
+ 'CanTakePayment',
15
+ 'DateCreated',
16
+ 'BelongsToEnrollment',
17
+ 'Address',
18
+ 'AddressID',
19
+ 'AllowAutoPay',
20
+ 'AppointmentTreatments',
21
+ 'BelongsToGroup',
22
+ 'BelongsToGroupAndGroupOrder',
23
+ 'BelongsToOrder',
24
+ 'CanCancel',
25
+ 'CanCheckin',
26
+ 'CanHaveCustomer2',
27
+ 'CanRevertNoShow',
28
+ 'CanUndoCheckin',
29
+ 'CancellationID',
30
+ 'Customer',
31
+ 'Customer2',
32
+ 'Customer2ID',
33
+ 'CustomerID',
34
+ 'CustomerLastName',
35
+ 'CustomerMobilePhone',
36
+ 'CustomerWorkPhone',
37
+ 'DateBooked',
38
+ 'DateNoShow',
39
+ 'Employee',
40
+ 'EmployeeFirstName',
41
+ 'EmployeeLastName',
42
+ 'GroupID',
43
+ 'GroupName',
44
+ 'GroupNumber',
45
+ 'GroupTypeID',
46
+ 'IsCancelledOrNoShow',
47
+ 'IsCheckedInInService',
48
+ 'IsPartOfClassPackageBooking',
49
+ 'IsPreBookedAtPastCheckout',
50
+ 'IsRecurring',
51
+ 'IsWebBooking',
52
+ 'Notes',
53
+ 'OrderID',
54
+ 'OrderStatusID',
55
+ 'PackageID',
56
+ 'PaymentID',
57
+ 'PaymentItemID',
58
+ 'PrimaryAppointmentTreatmentID',
59
+ 'RecurrenceID',
60
+ 'Room',
61
+ 'Source',
62
+ 'Treatment',
63
+ 'TreatmentName',
64
+ 'Type',
65
+ 'IsHeld',
66
+ 'HoldForMinutes',
67
+ 'HeldSince',
68
+ 'IsServiceComplete',
69
+ 'IsCheckout',
70
+ 'DateCheckIn',
71
+ 'IsFromWaitList',
72
+ 'IsFromClassWaitList',
73
+ 'CustomerRecordTypeID',
74
+ 'CustomerParentID'
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,51 @@
1
+ module Booker
2
+ module Models
3
+ class AppointmentTreatment < Model
4
+ attr_accessor 'AppointmentID',
5
+ 'DynamicPrice',
6
+ 'EndDateTime',
7
+ 'ID',
8
+ 'StartDateTime',
9
+ 'ChildID',
10
+ 'ChildName',
11
+ 'AllowChangeStartTime',
12
+ 'DynamicPriceID',
13
+ 'Employee',
14
+ 'Employee2FullName',
15
+ 'Employee2ID',
16
+ 'EmployeeFirstName',
17
+ 'EmployeeFullName',
18
+ 'EmployeeID',
19
+ 'EmployeeLastName',
20
+ 'EmployeeRecoveryDuration',
21
+ 'EmployeeTypeID',
22
+ 'EmployeeWasRequested',
23
+ 'FinishStartDateTime',
24
+ 'FinishTimeAppliedToEmployee',
25
+ 'FinishTimeAppliedToRoom',
26
+ 'FinishTimeDuration',
27
+ 'FinishTimeOriginalDuration',
28
+ 'ProcessingStartDateTime',
29
+ 'ProcessingTimeAppliedToRoom',
30
+ 'ProcessingTimeAppliedToEmployee',
31
+ 'ProcessingTimeDuration',
32
+ 'ProcessingTimeOriginalDuration',
33
+ 'RequiresProcessingTime',
34
+ 'Room',
35
+ 'RoomID',
36
+ 'RoomName',
37
+ 'RoomRecoveryDuration',
38
+ 'StartTimeDuration',
39
+ 'StartTimeOriginalDuration',
40
+ 'TagPrice',
41
+ 'Treatment',
42
+ 'TreatmentDuration',
43
+ 'TreatmentID',
44
+ 'TreatmentIsForCouples',
45
+ 'TreatmentName',
46
+ 'ClassInstanceID',
47
+ 'IsDurationOverridden'
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,13 @@
1
+ module Booker
2
+ module Models
3
+ class AvailableTime < Model
4
+ attr_accessor 'CurrentPrice',
5
+ 'Duration',
6
+ 'EmployeeID',
7
+ 'StartDateTime',
8
+ 'TreatmentID',
9
+ 'RoomID',
10
+ 'Employee2ID'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class BusinessType < Type; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class Category < Type; end
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ module Booker
2
+ module Models
3
+ class ClassInstance < Model
4
+ attr_accessor 'ID',
5
+ 'EndDateTime',
6
+ 'HasClassFilled',
7
+ 'IsForMembersOnly',
8
+ 'IsRecurring',
9
+ 'IsSpecialEvent',
10
+ 'IsWorkshop',
11
+ 'NumReserved',
12
+ 'Price',
13
+ 'RoomName',
14
+ 'StartDateTime',
15
+ 'Teacher',
16
+ 'Teacher2',
17
+ 'TotalCapacity',
18
+ 'TreatmentDuration',
19
+ 'ListAsSubstitute',
20
+ 'IsEnrollable',
21
+ 'SeriesID',
22
+ 'Treatment'
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class Country < Type; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class CurrentPrice < Price; end
4
+ end
5
+ end
@@ -0,0 +1,51 @@
1
+ module Booker
2
+ module Models
3
+ class Customer < Model
4
+ attr_accessor 'CustomerID',
5
+ 'GUID',
6
+ 'Address',
7
+ 'AllowReceiveEmails',
8
+ 'AllowReceiveSMS',
9
+ 'SendEmail',
10
+ 'CellPhone',
11
+ 'CreditCard',
12
+ 'Email',
13
+ 'FirstName',
14
+ 'HasActiveMembership',
15
+ 'HomePhone',
16
+ 'MobilePhone',
17
+ 'LastName',
18
+ 'WorkPhone',
19
+ 'WorkPhoneExt',
20
+ 'ShippingAddress',
21
+ 'CustomerRecordType',
22
+ 'DateOfBirth',
23
+ 'Gender',
24
+ 'GenderID',
25
+ 'HasMembership',
26
+ 'HasPastMembership',
27
+ 'IsNewCustomer',
28
+ 'LoyaltyPoints',
29
+ 'LocationID',
30
+ 'LocationName',
31
+ 'NumberOfReferrals',
32
+ 'PreferredStaffGender',
33
+ 'EmergencyContactName',
34
+ 'EmergencyContactPhone',
35
+ 'EmergencyContactRelationship',
36
+ 'IsActive',
37
+ 'Occupation',
38
+ 'PreferredStaffMemberID',
39
+ 'ReferredByCustomerID'
40
+
41
+ def self.from_list(array)
42
+ if array.any? && array.first['Customer']
43
+ flattened = array.map{|a| a['Customer'].merge('CustomerID' => a['CustomerID'])}
44
+ super(flattened)
45
+ else
46
+ super
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class Customer2 < Customer; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class CustomerRecordType < Type; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class Discount < Price; end
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ module Booker
2
+ module Models
3
+ class DynamicPrice < Model
4
+ attr_accessor 'Discount',
5
+ 'FinalPrice',
6
+ 'OriginalPrice',
7
+ 'ReceiptDisplayPrice',
8
+ 'OriginalTagPrice'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Booker
2
+ module Models
3
+ class Employee < Model
4
+ attr_accessor 'ID',
5
+ 'FirstName',
6
+ 'LastName',
7
+ 'Gender'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class FinalTotal < Price; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Booker
2
+ module Models
3
+ class Gender < Type; end
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ module Booker
2
+ module Models
3
+ class Location < Model
4
+ attr_accessor 'ID',
5
+ 'AccountName',
6
+ 'BusinessName',
7
+ 'BusinessType',
8
+ 'EmailAddress',
9
+ 'Address',
10
+ 'Phone',
11
+ 'TimeZone',
12
+ 'WebSite',
13
+ 'IsDistributionPartner',
14
+ 'EncryptedLocationID',
15
+ 'BrandAccountName'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,123 @@
1
+ module Booker
2
+ module Models
3
+ class Model
4
+
5
+ def initialize(options = {})
6
+ options.each do |key, value|
7
+ send(:"#{key}=", value)
8
+ end
9
+ end
10
+
11
+ def to_hash
12
+ hash = {}
13
+ self.instance_variables.each do |var|
14
+ value = self.instance_variable_get var
15
+ if value.is_a? Array
16
+ new_value = hash_list(value)
17
+ elsif value.is_a? Booker::Models::Model
18
+ new_value = value.to_hash
19
+ elsif value.is_a? Time
20
+ new_value = self.class.time_to_booker_datetime(value)
21
+ elsif value.is_a? Date
22
+ time = value.in_time_zone
23
+ new_value = self.class.time_to_booker_datetime(time)
24
+ else
25
+ new_value = value
26
+ end
27
+ hash[var[1..-1]] = new_value
28
+ end
29
+ hash
30
+ end
31
+
32
+ def to_json
33
+ Oj.dump(to_hash, mode: :compat)
34
+ end
35
+
36
+ def self.from_hash(hash)
37
+ model = self.new
38
+ hash.each do |key, value|
39
+ if model.respond_to?(:"#{key}")
40
+ constantized = self.constantize(key)
41
+ if constantized
42
+ if value.is_a?(Array) && value.first.is_a?(Hash)
43
+ model.send(:"#{key}=", constantized.from_list(value))
44
+ next
45
+ elsif value.is_a? Hash
46
+ model.send(:"#{key}=", constantized.from_hash(value))
47
+ next
48
+ end
49
+ end
50
+
51
+ if value.is_a?(String) && value.start_with?('/Date(')
52
+ model.send(:"#{key}=", time_from_booker_datetime(value))
53
+ elsif !value.nil?
54
+ model.send(:"#{key}=", value)
55
+ end
56
+ end
57
+ end
58
+ model
59
+ end
60
+
61
+ def self.from_list(array)
62
+ array.map{|item| self.from_hash(item)}
63
+ end
64
+
65
+ def self.constantize(key)
66
+ begin
67
+ Booker::Models.const_get("Booker::Models::#{key.singularize}")
68
+ rescue NameError
69
+ nil
70
+ end
71
+ end
72
+
73
+ # Booker's API hands you back all time as if the business is in server time.
74
+ # First load the time in server time, then return the same hours and minutes in current time zone.
75
+ # Booker will hopefully fix this in a future API version. Sorry.
76
+ def self.time_from_booker_datetime(booker_datetime)
77
+ timestamp = booker_datetime[/\/Date\((.\d+)[\-\+]/, 1].to_i / 1000.to_f
78
+
79
+ original_tz = Time.zone
80
+ begin
81
+ # Booker's server is always EST
82
+ Time.zone = Booker::Client::TimeZone
83
+
84
+ booker_time = Time.zone.at(timestamp)
85
+ ensure
86
+ Time.zone = original_tz
87
+ end
88
+
89
+ # Convert it back to location time without changing hours and minutes
90
+ Time.zone.parse(booker_time.strftime('%Y-%m-%d %H:%M:%S'))
91
+ end
92
+
93
+ # Booker's API requires times to be sent in as if the business is in Eastern Time!
94
+ def self.time_to_booker_datetime(time)
95
+ original_tz = Time.zone
96
+
97
+ begin
98
+ # Booker's server is always EST
99
+ Time.zone = Booker::Client::TimeZone
100
+ timestamp = (Time.zone.parse(time.strftime("%Y-%m-%dT%H:%M:%S")).to_f * 1000).to_i
101
+ ensure
102
+ Time.zone = original_tz
103
+ end
104
+
105
+ "/Date(#{timestamp})/"
106
+ end
107
+
108
+ private
109
+
110
+ def hash_list(array)
111
+ array.map do |item|
112
+ if item.is_a? Array
113
+ hash_list(item)
114
+ elsif item.is_a? Booker::Models::Model
115
+ item.to_hash
116
+ else
117
+ item
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end