crisphive 0.2.0 → 0.3.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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +98 -10
  3. data/lib/crisphive/api/business_skill_api.rb +348 -0
  4. data/lib/crisphive/api/customer_api.rb +7 -4
  5. data/lib/crisphive/api/job_request_business_api.rb +243 -27
  6. data/lib/crisphive/api/job_types_api.rb +208 -0
  7. data/lib/crisphive/api/permission_api.rb +79 -0
  8. data/lib/crisphive/api/service_area_api.rb +208 -0
  9. data/lib/crisphive/api/technician_api.rb +8 -8
  10. data/lib/crisphive/api/technician_time_off_api.rb +240 -0
  11. data/lib/crisphive/api/vehicle_api.rb +208 -0
  12. data/lib/crisphive/api/webhooks_api.rb +213 -0
  13. data/lib/crisphive/models/api_internal_techtimeoff_actions.rb +232 -0
  14. data/lib/crisphive/models/api_internal_techtimeoff_status.rb +42 -0
  15. data/lib/crisphive/models/assignable_group.rb +289 -0
  16. data/lib/crisphive/models/book_and_confirm_job_request200_response.rb +253 -0
  17. data/lib/crisphive/models/commit_absence_resolve200_response.rb +253 -0
  18. data/lib/crisphive/models/create_job_type200_response.rb +253 -0
  19. data/lib/crisphive/models/create_service_area200_response.rb +253 -0
  20. data/lib/crisphive/models/create_skill200_response.rb +253 -0
  21. data/lib/crisphive/models/create_skill_category200_response.rb +253 -0
  22. data/lib/crisphive/models/create_technician_time_off200_response.rb +253 -0
  23. data/lib/crisphive/models/create_vehicle200_response.rb +253 -0
  24. data/lib/crisphive/models/create_webhook_endpoint200_response.rb +253 -0
  25. data/lib/crisphive/models/customer.rb +11 -1
  26. data/lib/crisphive/models/customer_contact.rb +25 -5
  27. data/lib/crisphive/models/customer_create_request.rb +12 -2
  28. data/lib/crisphive/models/customer_list_item.rb +11 -1
  29. data/lib/crisphive/models/customer_quick_books_link.rb +235 -0
  30. data/lib/crisphive/models/customer_service_area_ref.rb +225 -0
  31. data/lib/crisphive/models/customer_technician_ref.rb +225 -0
  32. data/lib/crisphive/models/customer_update_request.rb +23 -20
  33. data/lib/crisphive/models/internal_jobrequest_http_address_req.rb +475 -0
  34. data/lib/crisphive/models/job_request.rb +11 -1
  35. data/lib/crisphive/models/job_request_absence_alternative.rb +356 -0
  36. data/lib/crisphive/models/job_request_absence_alternative_cost.rb +275 -0
  37. data/lib/crisphive/models/job_request_absence_assignment.rb +319 -0
  38. data/lib/crisphive/models/job_request_absence_commit_request.rb +296 -0
  39. data/lib/crisphive/models/job_request_absence_notification.rb +283 -0
  40. data/lib/crisphive/models/job_request_absence_plan.rb +322 -0
  41. data/lib/crisphive/models/job_request_absence_preview_request.rb +280 -0
  42. data/lib/crisphive/models/job_request_absence_resolved_job.rb +499 -0
  43. data/lib/crisphive/models/job_request_absence_solver.rb +289 -0
  44. data/lib/crisphive/models/job_request_absence_time_off.rb +281 -0
  45. data/lib/crisphive/models/job_request_absence_unresolved_job.rb +364 -0
  46. data/lib/crisphive/models/job_request_action_summary.rb +1 -1
  47. data/lib/crisphive/models/job_request_attention_summary.rb +2 -2
  48. data/lib/crisphive/models/job_request_blocker.rb +363 -0
  49. data/lib/crisphive/models/job_request_blocker_ref.rb +223 -0
  50. data/lib/crisphive/models/job_request_book_and_confirm_customer.rb +302 -0
  51. data/lib/crisphive/models/job_request_book_and_confirm_emergency.rb +315 -0
  52. data/lib/crisphive/models/job_request_book_and_confirm_emergency_result.rb +279 -0
  53. data/lib/crisphive/models/job_request_book_and_confirm_refusal.rb +280 -0
  54. data/lib/crisphive/models/job_request_book_and_confirm_request.rb +466 -0
  55. data/lib/crisphive/models/job_request_book_and_confirm_response.rb +295 -0
  56. data/lib/crisphive/models/job_request_confirm_request.rb +14 -4
  57. data/lib/crisphive/models/job_request_create_request.rb +1 -1
  58. data/lib/crisphive/models/job_request_emergency_candidate.rb +26 -4
  59. data/lib/crisphive/models/job_request_emergency_candidates.rb +1 -1
  60. data/lib/crisphive/models/job_request_emergency_candidates_request.rb +24 -11
  61. data/lib/crisphive/models/job_request_emergency_commit_request.rb +11 -1
  62. data/lib/crisphive/models/job_request_emergency_inline_job.rb +353 -0
  63. data/lib/crisphive/models/job_request_emergency_plan.rb +25 -3
  64. data/lib/crisphive/models/job_request_emergency_preview_request.rb +24 -11
  65. data/lib/crisphive/models/job_request_move_commit_req.rb +11 -1
  66. data/lib/crisphive/models/job_request_move_plan.rb +11 -1
  67. data/lib/crisphive/models/job_request_move_preview_req.rb +11 -1
  68. data/lib/crisphive/models/job_request_move_warning.rb +32 -8
  69. data/lib/crisphive/models/job_request_priority_update_result.rb +217 -0
  70. data/lib/crisphive/models/job_request_quote_request.rb +14 -11
  71. data/lib/crisphive/models/job_request_reassign_fallback.rb +287 -0
  72. data/lib/crisphive/models/job_request_skill_summary.rb +1 -1
  73. data/lib/crisphive/models/job_request_status_summary.rb +1 -1
  74. data/lib/crisphive/models/job_request_time_segments.rb +2 -2
  75. data/lib/crisphive/models/job_type.rb +42 -2
  76. data/lib/crisphive/models/job_type_create_request.rb +399 -0
  77. data/lib/crisphive/models/job_type_create_response.rb +215 -0
  78. data/lib/crisphive/models/job_type_update_request.rb +400 -0
  79. data/lib/crisphive/models/list_assignable_groups200_response.rb +255 -0
  80. data/lib/crisphive/models/list_technician_time_off200_response.rb +253 -0
  81. data/lib/crisphive/models/list_webhook_event_types200_response.rb +255 -0
  82. data/lib/crisphive/models/quote_job_request200_response.rb +253 -0
  83. data/lib/crisphive/models/service_area.rb +21 -1
  84. data/lib/crisphive/models/service_area_create_request.rb +455 -0
  85. data/lib/crisphive/models/service_area_create_response.rb +215 -0
  86. data/lib/crisphive/models/service_area_update_request.rb +451 -0
  87. data/lib/crisphive/models/skill_category_create_request.rb +270 -0
  88. data/lib/crisphive/models/skill_category_create_response.rb +215 -0
  89. data/lib/crisphive/models/skill_create_request.rb +270 -0
  90. data/lib/crisphive/models/skill_create_response.rb +215 -0
  91. data/lib/crisphive/models/skill_update_request.rb +281 -0
  92. data/lib/crisphive/models/technician.rb +64 -2
  93. data/lib/crisphive/models/technician_create_request.rb +14 -11
  94. data/lib/crisphive/models/technician_time_off.rb +334 -0
  95. data/lib/crisphive/models/technician_time_off_create_request.rb +285 -0
  96. data/lib/crisphive/models/technician_time_off_create_response.rb +215 -0
  97. data/lib/crisphive/models/technician_time_off_list.rb +246 -0
  98. data/lib/crisphive/models/technician_update_request.rb +2 -2
  99. data/lib/crisphive/models/vehicle_create_request.rb +420 -0
  100. data/lib/crisphive/models/vehicle_create_response.rb +215 -0
  101. data/lib/crisphive/models/vehicle_update_request.rb +440 -0
  102. data/lib/crisphive/models/webhook_create_request.rb +320 -0
  103. data/lib/crisphive/models/webhook_create_response.rb +391 -0
  104. data/lib/crisphive/models/webhook_verification.rb +235 -0
  105. data/lib/crisphive/version.rb +1 -1
  106. data/lib/crisphive.rb +66 -0
  107. metadata +68 -2
@@ -0,0 +1,353 @@
1
+ =begin
2
+ #Crisphive Developer API
3
+
4
+ #Public REST API for integrating Crisphive from your own backend. Authenticate every request with a secret API key as a Bearer token (`Authorization: Bearer chsk_live_…`). The key prefix selects the data environment: `chsk_live_…` → production (live), `chsk_test_…` → sandbox (isolated test). **Key scopes (restricted keys).** A key is either *full-access* (can call every endpoint below) or *restricted* to a set of permission codes chosen at creation — the same codes as the dashboard permission grid (e.g. `customers_view`, `job_create`, `team_manage`). A restricted key calling an endpoint outside its scope gets `403`. The full code list is the permission catalog (`GET /permission/modules` on the dashboard API). Create, scope, and revoke keys from the business dashboard. Every response is wrapped in the envelope `{ \"error_code\": 0, \"message\": \"Success\", \"data\": <payload> }`.
5
+
6
+ The version of the OpenAPI document: 1.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.11.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Crisphive
17
+ class JobRequestEmergencyInlineJob
18
+ # Service address for a caller who does not exist yet. Geocoded when it carries no coordinates.
19
+ attr_accessor :address
20
+
21
+ # UUID of an existing customer — their stored address is used. Send this OR `address`.
22
+ attr_accessor :customer_id
23
+
24
+ # Demobilization minutes after the work — same rules as mobilization_minutes.
25
+ attr_accessor :demobilization_minutes
26
+
27
+ # Hands-on work minutes. Optional when the job type carries a default.
28
+ attr_accessor :job_duration_minutes
29
+
30
+ # UUID of the job type: supplies default_duration_minutes when job_duration_minutes is omitted. Optional — omitted, the business's default job type applies.
31
+ attr_accessor :job_type_id
32
+
33
+ # Mobilization minutes before the work — same fallback rules as quoteJobRequest.
34
+ attr_accessor :mobilization_minutes
35
+
36
+ # UUIDs of skills the work needs. Optional; up to 20.
37
+ attr_accessor :skill_ids
38
+
39
+ # Attribute mapping from ruby-style variable name to JSON key.
40
+ def self.attribute_map
41
+ {
42
+ :'address' => :'address',
43
+ :'customer_id' => :'customer_id',
44
+ :'demobilization_minutes' => :'demobilization_minutes',
45
+ :'job_duration_minutes' => :'job_duration_minutes',
46
+ :'job_type_id' => :'job_type_id',
47
+ :'mobilization_minutes' => :'mobilization_minutes',
48
+ :'skill_ids' => :'skill_ids'
49
+ }
50
+ end
51
+
52
+ # Returns all the JSON keys this model knows about
53
+ def self.acceptable_attributes
54
+ attribute_map.values
55
+ end
56
+
57
+ # Attribute type mapping.
58
+ def self.openapi_types
59
+ {
60
+ :'address' => :'InternalJobrequestHttpAddressReq',
61
+ :'customer_id' => :'String',
62
+ :'demobilization_minutes' => :'Integer',
63
+ :'job_duration_minutes' => :'Integer',
64
+ :'job_type_id' => :'String',
65
+ :'mobilization_minutes' => :'Integer',
66
+ :'skill_ids' => :'Array<String>'
67
+ }
68
+ end
69
+
70
+ # List of attributes with nullable: true
71
+ def self.openapi_nullable
72
+ Set.new([
73
+ ])
74
+ end
75
+
76
+ # Initializes the object
77
+ # @param [Hash] attributes Model attributes in the form of hash
78
+ def initialize(attributes = {})
79
+ if (!attributes.is_a?(Hash))
80
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Crisphive::JobRequestEmergencyInlineJob` initialize method"
81
+ end
82
+
83
+ # check to see if the attribute exists and convert string to symbol for hash key
84
+ attributes = attributes.each_with_object({}) { |(k, v), h|
85
+ if (!self.class.attribute_map.key?(k.to_sym))
86
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Crisphive::JobRequestEmergencyInlineJob`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
87
+ end
88
+ h[k.to_sym] = v
89
+ }
90
+
91
+ if attributes.key?(:'address')
92
+ self.address = attributes[:'address']
93
+ end
94
+
95
+ if attributes.key?(:'customer_id')
96
+ self.customer_id = attributes[:'customer_id']
97
+ end
98
+
99
+ if attributes.key?(:'demobilization_minutes')
100
+ self.demobilization_minutes = attributes[:'demobilization_minutes']
101
+ end
102
+
103
+ if attributes.key?(:'job_duration_minutes')
104
+ self.job_duration_minutes = attributes[:'job_duration_minutes']
105
+ end
106
+
107
+ if attributes.key?(:'job_type_id')
108
+ self.job_type_id = attributes[:'job_type_id']
109
+ end
110
+
111
+ if attributes.key?(:'mobilization_minutes')
112
+ self.mobilization_minutes = attributes[:'mobilization_minutes']
113
+ end
114
+
115
+ if attributes.key?(:'skill_ids')
116
+ if (value = attributes[:'skill_ids']).is_a?(Array)
117
+ self.skill_ids = value
118
+ end
119
+ end
120
+ end
121
+
122
+ # Show invalid properties with the reasons. Usually used together with valid?
123
+ # @return Array for valid properties with the reasons
124
+ def list_invalid_properties
125
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
126
+ invalid_properties = Array.new
127
+ if !@demobilization_minutes.nil? && @demobilization_minutes < 0
128
+ invalid_properties.push('invalid value for "demobilization_minutes", must be greater than or equal to 0.')
129
+ end
130
+
131
+ if !@job_duration_minutes.nil? && @job_duration_minutes < 1
132
+ invalid_properties.push('invalid value for "job_duration_minutes", must be greater than or equal to 1.')
133
+ end
134
+
135
+ if !@mobilization_minutes.nil? && @mobilization_minutes < 0
136
+ invalid_properties.push('invalid value for "mobilization_minutes", must be greater than or equal to 0.')
137
+ end
138
+
139
+ if !@skill_ids.nil? && @skill_ids.length > 20
140
+ invalid_properties.push('invalid value for "skill_ids", number of items must be less than or equal to 20.')
141
+ end
142
+
143
+ invalid_properties
144
+ end
145
+
146
+ # Check to see if the all the properties in the model are valid
147
+ # @return true if the model is valid
148
+ def valid?
149
+ warn '[DEPRECATED] the `valid?` method is obsolete'
150
+ return false if !@demobilization_minutes.nil? && @demobilization_minutes < 0
151
+ return false if !@job_duration_minutes.nil? && @job_duration_minutes < 1
152
+ return false if !@mobilization_minutes.nil? && @mobilization_minutes < 0
153
+ return false if !@skill_ids.nil? && @skill_ids.length > 20
154
+ true
155
+ end
156
+
157
+ # Custom attribute writer method with validation
158
+ # @param [Object] demobilization_minutes Value to be assigned
159
+ def demobilization_minutes=(demobilization_minutes)
160
+ if demobilization_minutes.nil?
161
+ fail ArgumentError, 'demobilization_minutes cannot be nil'
162
+ end
163
+
164
+ if demobilization_minutes < 0
165
+ fail ArgumentError, 'invalid value for "demobilization_minutes", must be greater than or equal to 0.'
166
+ end
167
+
168
+ @demobilization_minutes = demobilization_minutes
169
+ end
170
+
171
+ # Custom attribute writer method with validation
172
+ # @param [Object] job_duration_minutes Value to be assigned
173
+ def job_duration_minutes=(job_duration_minutes)
174
+ if job_duration_minutes.nil?
175
+ fail ArgumentError, 'job_duration_minutes cannot be nil'
176
+ end
177
+
178
+ if job_duration_minutes < 1
179
+ fail ArgumentError, 'invalid value for "job_duration_minutes", must be greater than or equal to 1.'
180
+ end
181
+
182
+ @job_duration_minutes = job_duration_minutes
183
+ end
184
+
185
+ # Custom attribute writer method with validation
186
+ # @param [Object] mobilization_minutes Value to be assigned
187
+ def mobilization_minutes=(mobilization_minutes)
188
+ if mobilization_minutes.nil?
189
+ fail ArgumentError, 'mobilization_minutes cannot be nil'
190
+ end
191
+
192
+ if mobilization_minutes < 0
193
+ fail ArgumentError, 'invalid value for "mobilization_minutes", must be greater than or equal to 0.'
194
+ end
195
+
196
+ @mobilization_minutes = mobilization_minutes
197
+ end
198
+
199
+ # Custom attribute writer method with validation
200
+ # @param [Object] skill_ids Value to be assigned
201
+ def skill_ids=(skill_ids)
202
+ if skill_ids.nil?
203
+ fail ArgumentError, 'skill_ids cannot be nil'
204
+ end
205
+
206
+ if skill_ids.length > 20
207
+ fail ArgumentError, 'invalid value for "skill_ids", number of items must be less than or equal to 20.'
208
+ end
209
+
210
+ @skill_ids = skill_ids
211
+ end
212
+
213
+ # Checks equality by comparing each attribute.
214
+ # @param [Object] Object to be compared
215
+ def ==(o)
216
+ return true if self.equal?(o)
217
+ self.class == o.class &&
218
+ address == o.address &&
219
+ customer_id == o.customer_id &&
220
+ demobilization_minutes == o.demobilization_minutes &&
221
+ job_duration_minutes == o.job_duration_minutes &&
222
+ job_type_id == o.job_type_id &&
223
+ mobilization_minutes == o.mobilization_minutes &&
224
+ skill_ids == o.skill_ids
225
+ end
226
+
227
+ # @see the `==` method
228
+ # @param [Object] Object to be compared
229
+ def eql?(o)
230
+ self == o
231
+ end
232
+
233
+ # Calculates hash code according to all attributes.
234
+ # @return [Integer] Hash code
235
+ def hash
236
+ [address, customer_id, demobilization_minutes, job_duration_minutes, job_type_id, mobilization_minutes, skill_ids].hash
237
+ end
238
+
239
+ # Builds the object from hash
240
+ # @param [Hash] attributes Model attributes in the form of hash
241
+ # @return [Object] Returns the model itself
242
+ def self.build_from_hash(attributes)
243
+ return nil unless attributes.is_a?(Hash)
244
+ attributes = attributes.transform_keys(&:to_sym)
245
+ transformed_hash = {}
246
+ openapi_types.each_pair do |key, type|
247
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
248
+ transformed_hash["#{key}"] = nil
249
+ elsif type =~ /\AArray<(.*)>/i
250
+ # check to ensure the input is an array given that the attribute
251
+ # is documented as an array but the input is not
252
+ if attributes[attribute_map[key]].is_a?(Array)
253
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
254
+ end
255
+ elsif !attributes[attribute_map[key]].nil?
256
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
257
+ end
258
+ end
259
+ new(transformed_hash)
260
+ end
261
+
262
+ # Deserializes the data based on type
263
+ # @param string type Data type
264
+ # @param string value Value to be deserialized
265
+ # @return [Object] Deserialized data
266
+ def self._deserialize(type, value)
267
+ case type.to_sym
268
+ when :Time
269
+ Time.parse(value)
270
+ when :Date
271
+ Date.parse(value)
272
+ when :String
273
+ value.to_s
274
+ when :Integer
275
+ value.to_i
276
+ when :Float
277
+ value.to_f
278
+ when :Boolean
279
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
280
+ true
281
+ else
282
+ false
283
+ end
284
+ when :Object
285
+ # generic object (usually a Hash), return directly
286
+ value
287
+ when /\AArray<(?<inner_type>.+)>\z/
288
+ inner_type = Regexp.last_match[:inner_type]
289
+ value.map { |v| _deserialize(inner_type, v) }
290
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
291
+ k_type = Regexp.last_match[:k_type]
292
+ v_type = Regexp.last_match[:v_type]
293
+ {}.tap do |hash|
294
+ value.each do |k, v|
295
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
296
+ end
297
+ end
298
+ else # model
299
+ # models (e.g. Pet) or oneOf
300
+ klass = Crisphive.const_get(type)
301
+ klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
302
+ end
303
+ end
304
+
305
+ # Returns the string representation of the object
306
+ # @return [String] String presentation of the object
307
+ def to_s
308
+ to_hash.to_s
309
+ end
310
+
311
+ # to_body is an alias to to_hash (backward compatibility)
312
+ # @return [Hash] Returns the object in the form of hash
313
+ def to_body
314
+ to_hash
315
+ end
316
+
317
+ # Returns the object in the form of hash
318
+ # @return [Hash] Returns the object in the form of hash
319
+ def to_hash
320
+ hash = {}
321
+ self.class.attribute_map.each_pair do |attr, param|
322
+ value = self.send(attr)
323
+ if value.nil?
324
+ is_nullable = self.class.openapi_nullable.include?(attr)
325
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
326
+ end
327
+
328
+ hash[param] = _to_hash(value)
329
+ end
330
+ hash
331
+ end
332
+
333
+ # Outputs non-array value in the form of hash
334
+ # For object, use to_hash. Otherwise, just return the value
335
+ # @param [Object] value Any valid value
336
+ # @return [Hash] Returns the value in the form of hash
337
+ def _to_hash(value)
338
+ if value.is_a?(Array)
339
+ value.compact.map { |v| _to_hash(v) }
340
+ elsif value.is_a?(Hash)
341
+ {}.tap do |hash|
342
+ value.each { |k, v| hash[k] = _to_hash(v) }
343
+ end
344
+ elsif value.respond_to? :to_hash
345
+ value.to_hash
346
+ else
347
+ value
348
+ end
349
+ end
350
+
351
+ end
352
+
353
+ end
@@ -15,6 +15,9 @@ require 'time'
15
15
 
16
16
  module Crisphive
17
17
  class JobRequestEmergencyPlan
18
+ # True on a PREVIEW onto a day the business does not work, sent without after_hours_override. The cascade is shown as the override would place it; to commit, confirm the coordinator has phoned the technician and send after_hours_override=true. Always false on a commit.
19
+ attr_accessor :after_hours_override_required
20
+
18
21
  # IANA timezone the per-day groupings are rendered in.
19
22
  attr_accessor :business_timezone
20
23
 
@@ -24,7 +27,7 @@ module Crisphive
24
27
  # Emergency visit window end (UTC) — start + the quoted visit duration (job + mobilization + demobilization).
25
28
  attr_accessor :emergency_end
26
29
 
27
- # ID of the inserted P0 job.
30
+ # ID of the inserted P0 job. Absent for a probe -- a `job` that does not exist yet.
28
31
  attr_accessor :emergency_job_id
29
32
 
30
33
  # Emergency visit window start (UTC).
@@ -33,6 +36,9 @@ module Crisphive
33
36
  # Cascade mode the plan assumed (overtime | next_day).
34
37
  attr_accessor :mode
35
38
 
39
+ # ReassignFallbacks: one entry per displaced job that reassign mode could NOT re-staff, and therefore left in days[].moves[] to be rescheduled. Empty in reschedule mode. Read this INSTEAD of inferring \"nobody was free\" from an empty reassignments[] — the two are different states (no fallbacks + empty reassignments means nothing was displaced at all).
40
+ attr_accessor :reassign_fallbacks
41
+
36
42
  # Displaced jobs handed to an ALTERNATE technician at their original window (displacement_mode=reassign; empty otherwise). Jobs that could not be re-staffed remain in days/total_moves (reschedule fallback).
37
43
  attr_accessor :reassignments
38
44
 
@@ -42,7 +48,7 @@ module Crisphive
42
48
  # Number of displaced jobs pushed to a later window.
43
49
  attr_accessor :total_moves
44
50
 
45
- # Non-blocking consequences the coordinator accepts by committing (TIME_OFF_OVERLAP per displaced job landing in the tech's approved leave).
51
+ # Non-blocking consequences the coordinator accepts by committing (TIME_OFF_OVERLAP per displaced job landing in the tech's approved leave, CALENDAR_OVERLAP per displaced job landing on a personal calendar event).
46
52
  attr_accessor :warnings
47
53
 
48
54
  class EnumAttributeValidator
@@ -70,12 +76,14 @@ module Crisphive
70
76
  # Attribute mapping from ruby-style variable name to JSON key.
71
77
  def self.attribute_map
72
78
  {
79
+ :'after_hours_override_required' => :'after_hours_override_required',
73
80
  :'business_timezone' => :'business_timezone',
74
81
  :'days' => :'days',
75
82
  :'emergency_end' => :'emergency_end',
76
83
  :'emergency_job_id' => :'emergency_job_id',
77
84
  :'emergency_start' => :'emergency_start',
78
85
  :'mode' => :'mode',
86
+ :'reassign_fallbacks' => :'reassign_fallbacks',
79
87
  :'reassignments' => :'reassignments',
80
88
  :'technician_id' => :'technician_id',
81
89
  :'total_moves' => :'total_moves',
@@ -91,12 +99,14 @@ module Crisphive
91
99
  # Attribute type mapping.
92
100
  def self.openapi_types
93
101
  {
102
+ :'after_hours_override_required' => :'Boolean',
94
103
  :'business_timezone' => :'String',
95
104
  :'days' => :'Array<JobRequestRescheduleDay>',
96
105
  :'emergency_end' => :'Time',
97
106
  :'emergency_job_id' => :'String',
98
107
  :'emergency_start' => :'Time',
99
108
  :'mode' => :'String',
109
+ :'reassign_fallbacks' => :'Array<JobRequestReassignFallback>',
100
110
  :'reassignments' => :'Array<JobRequestRescheduleReassignment>',
101
111
  :'technician_id' => :'String',
102
112
  :'total_moves' => :'Integer',
@@ -125,6 +135,10 @@ module Crisphive
125
135
  h[k.to_sym] = v
126
136
  }
127
137
 
138
+ if attributes.key?(:'after_hours_override_required')
139
+ self.after_hours_override_required = attributes[:'after_hours_override_required']
140
+ end
141
+
128
142
  if attributes.key?(:'business_timezone')
129
143
  self.business_timezone = attributes[:'business_timezone']
130
144
  end
@@ -151,6 +165,12 @@ module Crisphive
151
165
  self.mode = attributes[:'mode']
152
166
  end
153
167
 
168
+ if attributes.key?(:'reassign_fallbacks')
169
+ if (value = attributes[:'reassign_fallbacks']).is_a?(Array)
170
+ self.reassign_fallbacks = value
171
+ end
172
+ end
173
+
154
174
  if attributes.key?(:'reassignments')
155
175
  if (value = attributes[:'reassignments']).is_a?(Array)
156
176
  self.reassignments = value
@@ -204,12 +224,14 @@ module Crisphive
204
224
  def ==(o)
205
225
  return true if self.equal?(o)
206
226
  self.class == o.class &&
227
+ after_hours_override_required == o.after_hours_override_required &&
207
228
  business_timezone == o.business_timezone &&
208
229
  days == o.days &&
209
230
  emergency_end == o.emergency_end &&
210
231
  emergency_job_id == o.emergency_job_id &&
211
232
  emergency_start == o.emergency_start &&
212
233
  mode == o.mode &&
234
+ reassign_fallbacks == o.reassign_fallbacks &&
213
235
  reassignments == o.reassignments &&
214
236
  technician_id == o.technician_id &&
215
237
  total_moves == o.total_moves &&
@@ -225,7 +247,7 @@ module Crisphive
225
247
  # Calculates hash code according to all attributes.
226
248
  # @return [Integer] Hash code
227
249
  def hash
228
- [business_timezone, days, emergency_end, emergency_job_id, emergency_start, mode, reassignments, technician_id, total_moves, warnings].hash
250
+ [after_hours_override_required, business_timezone, days, emergency_end, emergency_job_id, emergency_start, mode, reassign_fallbacks, reassignments, technician_id, total_moves, warnings].hash
229
251
  end
230
252
 
231
253
  # Builds the object from hash
@@ -15,16 +15,22 @@ require 'time'
15
15
 
16
16
  module Crisphive
17
17
  class JobRequestEmergencyPreviewRequest
18
+ # Place this P0 outside working hours / approved time-off — you have phoned the technician and they agreed. Drops the non-working-day rejection; the response then carries an AFTER_HOURS warning. Double-booking, service area, required skills and the lead-tier rule still reject.
19
+ attr_accessor :after_hours_override
20
+
18
21
  # Fate of displaced jobs: reschedule (default — pushed to later windows) or reassign (handed to another feasible technician at their ORIGINAL time; no-capacity jobs fall back to reschedule).
19
22
  attr_accessor :displacement_mode
20
23
 
21
- # ID of the P0 job to insert.
24
+ # UUID of the P0 job to insert. Send this OR `job`, never both and never neither.
22
25
  attr_accessor :emergency_job_id
23
26
 
27
+ # A job that does not exist yet — the wizard's read-only preview before anything is written. Send this OR `emergency_job_id`.
28
+ attr_accessor :job
29
+
24
30
  # Cascade mode: overtime = displaced jobs stay same-day (tech works late); next_day = overflow rolls to the next working day.
25
31
  attr_accessor :mode
26
32
 
27
- # Desired start — business-local naive datetime, no offset. Must be in the future.
33
+ # Desired start — business-local wall clock. Seconds may be omitted and a space may replace the T; an offset is accepted only when it agrees with the business timezone (a disagreeing one is refused with JOB_REQUEST_INVALID_INPUT rather than guessed). Must be in the future.
28
34
  attr_accessor :start_at
29
35
 
30
36
  # Target technician (must belong to the business).
@@ -55,8 +61,10 @@ module Crisphive
55
61
  # Attribute mapping from ruby-style variable name to JSON key.
56
62
  def self.attribute_map
57
63
  {
64
+ :'after_hours_override' => :'after_hours_override',
58
65
  :'displacement_mode' => :'displacement_mode',
59
66
  :'emergency_job_id' => :'emergency_job_id',
67
+ :'job' => :'job',
60
68
  :'mode' => :'mode',
61
69
  :'start_at' => :'start_at',
62
70
  :'technician_id' => :'technician_id'
@@ -71,10 +79,12 @@ module Crisphive
71
79
  # Attribute type mapping.
72
80
  def self.openapi_types
73
81
  {
82
+ :'after_hours_override' => :'Boolean',
74
83
  :'displacement_mode' => :'String',
75
84
  :'emergency_job_id' => :'String',
85
+ :'job' => :'JobRequestEmergencyInlineJob',
76
86
  :'mode' => :'String',
77
- :'start_at' => :'String',
87
+ :'start_at' => :'Time',
78
88
  :'technician_id' => :'String'
79
89
  }
80
90
  end
@@ -100,14 +110,20 @@ module Crisphive
100
110
  h[k.to_sym] = v
101
111
  }
102
112
 
113
+ if attributes.key?(:'after_hours_override')
114
+ self.after_hours_override = attributes[:'after_hours_override']
115
+ end
116
+
103
117
  if attributes.key?(:'displacement_mode')
104
118
  self.displacement_mode = attributes[:'displacement_mode']
105
119
  end
106
120
 
107
121
  if attributes.key?(:'emergency_job_id')
108
122
  self.emergency_job_id = attributes[:'emergency_job_id']
109
- else
110
- self.emergency_job_id = nil
123
+ end
124
+
125
+ if attributes.key?(:'job')
126
+ self.job = attributes[:'job']
111
127
  end
112
128
 
113
129
  if attributes.key?(:'mode')
@@ -134,10 +150,6 @@ module Crisphive
134
150
  def list_invalid_properties
135
151
  warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
136
152
  invalid_properties = Array.new
137
- if @emergency_job_id.nil?
138
- invalid_properties.push('invalid value for "emergency_job_id", emergency_job_id cannot be nil.')
139
- end
140
-
141
153
  if @mode.nil?
142
154
  invalid_properties.push('invalid value for "mode", mode cannot be nil.')
143
155
  end
@@ -159,7 +171,6 @@ module Crisphive
159
171
  warn '[DEPRECATED] the `valid?` method is obsolete'
160
172
  displacement_mode_validator = EnumAttributeValidator.new('String', ["reschedule", "reassign"])
161
173
  return false unless displacement_mode_validator.valid?(@displacement_mode)
162
- return false if @emergency_job_id.nil?
163
174
  return false if @mode.nil?
164
175
  mode_validator = EnumAttributeValidator.new('String', ["overtime", "next_day"])
165
176
  return false unless mode_validator.valid?(@mode)
@@ -193,8 +204,10 @@ module Crisphive
193
204
  def ==(o)
194
205
  return true if self.equal?(o)
195
206
  self.class == o.class &&
207
+ after_hours_override == o.after_hours_override &&
196
208
  displacement_mode == o.displacement_mode &&
197
209
  emergency_job_id == o.emergency_job_id &&
210
+ job == o.job &&
198
211
  mode == o.mode &&
199
212
  start_at == o.start_at &&
200
213
  technician_id == o.technician_id
@@ -209,7 +222,7 @@ module Crisphive
209
222
  # Calculates hash code according to all attributes.
210
223
  # @return [Integer] Hash code
211
224
  def hash
212
- [displacement_mode, emergency_job_id, mode, start_at, technician_id].hash
225
+ [after_hours_override, displacement_mode, emergency_job_id, job, mode, start_at, technician_id].hash
213
226
  end
214
227
 
215
228
  # Builds the object from hash
@@ -15,6 +15,9 @@ require 'time'
15
15
 
16
16
  module Crisphive
17
17
  class JobRequestMoveCommitReq
18
+ # AfterHoursOverride — drop the non-working-day rejection for a P0 whose technician the coordinator has already phoned. P0 only (JOB_REQUEST_AFTER_HOURS_REQUIRES_P0 otherwise), and the preview then carries an AFTER_HOURS warning. Commit must repeat what the preview was run with.
19
+ attr_accessor :after_hours_override
20
+
18
21
  # ExpectedMemberIDs — crew moves only: the FULL member set the preview staffed (echo data.members[].technician_id). If the commit's re-plan would staff a DIFFERENT set (a previewed replacement got booked in the meantime), the commit is rejected with SCHEDULE_MOVE_PLAN_DRIFTED — crew swaps are never approved unseen. Omit to opt out.
19
22
  attr_accessor :expected_member_ids
20
23
 
@@ -58,6 +61,7 @@ module Crisphive
58
61
  # Attribute mapping from ruby-style variable name to JSON key.
59
62
  def self.attribute_map
60
63
  {
64
+ :'after_hours_override' => :'after_hours_override',
61
65
  :'expected_member_ids' => :'expected_member_ids',
62
66
  :'expected_move_ids' => :'expected_move_ids',
63
67
  :'expected_version' => :'expected_version',
@@ -75,6 +79,7 @@ module Crisphive
75
79
  # Attribute type mapping.
76
80
  def self.openapi_types
77
81
  {
82
+ :'after_hours_override' => :'Boolean',
78
83
  :'expected_member_ids' => :'Array<String>',
79
84
  :'expected_move_ids' => :'Array<String>',
80
85
  :'expected_version' => :'Integer',
@@ -105,6 +110,10 @@ module Crisphive
105
110
  h[k.to_sym] = v
106
111
  }
107
112
 
113
+ if attributes.key?(:'after_hours_override')
114
+ self.after_hours_override = attributes[:'after_hours_override']
115
+ end
116
+
108
117
  if attributes.key?(:'expected_member_ids')
109
118
  if (value = attributes[:'expected_member_ids']).is_a?(Array)
110
119
  self.expected_member_ids = value
@@ -206,6 +215,7 @@ module Crisphive
206
215
  def ==(o)
207
216
  return true if self.equal?(o)
208
217
  self.class == o.class &&
218
+ after_hours_override == o.after_hours_override &&
209
219
  expected_member_ids == o.expected_member_ids &&
210
220
  expected_move_ids == o.expected_move_ids &&
211
221
  expected_version == o.expected_version &&
@@ -223,7 +233,7 @@ module Crisphive
223
233
  # Calculates hash code according to all attributes.
224
234
  # @return [Integer] Hash code
225
235
  def hash
226
- [expected_member_ids, expected_move_ids, expected_version, mode, start_at, technician_id].hash
236
+ [after_hours_override, expected_member_ids, expected_move_ids, expected_version, mode, start_at, technician_id].hash
227
237
  end
228
238
 
229
239
  # Builds the object from hash
@@ -15,6 +15,9 @@ require 'time'
15
15
 
16
16
  module Crisphive
17
17
  class JobRequestMovePlan
18
+ # True on a PREVIEW that lands a p0 single-person job on a day the business does not work, sent without after_hours_override. The plan is shown as the override would place it; to commit it, ask the coordinator whether they have phoned the technician and send after_hours_override=true. Always false on a commit (a commit without the flag refuses instead).
19
+ attr_accessor :after_hours_override_required
20
+
18
21
  # IANA timezone the per-day groupings are rendered in.
19
22
  attr_accessor :business_timezone
20
23
 
@@ -79,6 +82,7 @@ module Crisphive
79
82
  # Attribute mapping from ruby-style variable name to JSON key.
80
83
  def self.attribute_map
81
84
  {
85
+ :'after_hours_override_required' => :'after_hours_override_required',
82
86
  :'business_timezone' => :'business_timezone',
83
87
  :'crew_changes' => :'crew_changes',
84
88
  :'days' => :'days',
@@ -103,6 +107,7 @@ module Crisphive
103
107
  # Attribute type mapping.
104
108
  def self.openapi_types
105
109
  {
110
+ :'after_hours_override_required' => :'Boolean',
106
111
  :'business_timezone' => :'String',
107
112
  :'crew_changes' => :'Array<JobRequestCrewChange>',
108
113
  :'days' => :'Array<JobRequestRescheduleDay>',
@@ -140,6 +145,10 @@ module Crisphive
140
145
  h[k.to_sym] = v
141
146
  }
142
147
 
148
+ if attributes.key?(:'after_hours_override_required')
149
+ self.after_hours_override_required = attributes[:'after_hours_override_required']
150
+ end
151
+
143
152
  if attributes.key?(:'business_timezone')
144
153
  self.business_timezone = attributes[:'business_timezone']
145
154
  end
@@ -233,6 +242,7 @@ module Crisphive
233
242
  def ==(o)
234
243
  return true if self.equal?(o)
235
244
  self.class == o.class &&
245
+ after_hours_override_required == o.after_hours_override_required &&
236
246
  business_timezone == o.business_timezone &&
237
247
  crew_changes == o.crew_changes &&
238
248
  days == o.days &&
@@ -257,7 +267,7 @@ module Crisphive
257
267
  # Calculates hash code according to all attributes.
258
268
  # @return [Integer] Hash code
259
269
  def hash
260
- [business_timezone, crew_changes, days, job_id, members, mode, new_end, new_start, previous_technician_id, short_code, technician_id, total_moves, warnings].hash
270
+ [after_hours_override_required, business_timezone, crew_changes, days, job_id, members, mode, new_end, new_start, previous_technician_id, short_code, technician_id, total_moves, warnings].hash
261
271
  end
262
272
 
263
273
  # Builds the object from hash