seatschart 0.3.0 → 0.5.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +79 -11
  3. data/lib/seatschart/api/audit_api.rb +2 -2
  4. data/lib/seatschart/api/auth_api.rb +85 -8
  5. data/lib/seatschart/api/billing_api.rb +93 -8
  6. data/lib/seatschart/api/charts_api.rb +63 -63
  7. data/lib/seatschart/api/events_api.rb +130 -124
  8. data/lib/seatschart/api/public_api.rb +6 -6
  9. data/lib/seatschart/api/seasons_api.rb +88 -88
  10. data/lib/seatschart/api/seats_api.rb +6 -6
  11. data/lib/seatschart/api/usage_api.rb +4 -4
  12. data/lib/seatschart/api/workspace_api.rb +1229 -51
  13. data/lib/seatschart/models/{api_error.rb → api_error_body.rb} +7 -7
  14. data/lib/seatschart/models/delete_api_workspaces_by_workspace_id_keys_by_key_id200_response.rb +237 -0
  15. data/lib/seatschart/models/delete_api_workspaces_by_workspace_id_members_by_user_id200_response.rb +221 -0
  16. data/lib/seatschart/models/get_api_workspaces200_response_items_inner.rb +50 -4
  17. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_invitations200_response.rb +239 -0
  18. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_invitations200_response_invitations_inner.rb +286 -0
  19. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_keys200_response.rb +239 -0
  20. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_keys200_response_api_keys_inner.rb +321 -0
  21. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_members200_response.rb +239 -0
  22. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_members200_response_members_inner.rb +288 -0
  23. data/lib/seatschart/models/get_api_workspaces_overview200_response.rb +288 -0
  24. data/lib/seatschart/models/get_api_workspaces_overview200_response_account.rb +270 -0
  25. data/lib/seatschart/models/get_api_workspaces_overview200_response_account_charts.rb +233 -0
  26. data/lib/seatschart/models/get_api_workspaces_overview200_response_account_plan.rb +237 -0
  27. data/lib/seatschart/models/get_api_workspaces_overview200_response_items_inner.rb +439 -0
  28. data/lib/seatschart/models/get_api_workspaces_overview200_response_items_inner_revenue.rb +234 -0
  29. data/lib/seatschart/models/get_api_workspaces_overview200_response_items_inner_usage.rb +271 -0
  30. data/lib/seatschart/models/get_api_workspaces_overview200_response_seats.rb +431 -0
  31. data/lib/seatschart/models/get_api_workspaces_overview200_response_seats_overage.rb +233 -0
  32. data/lib/seatschart/models/get_api_workspaces_overview200_response_seats_projected.rb +237 -0
  33. data/lib/seatschart/models/get_api_workspaces_overview200_response_totals.rb +318 -0
  34. data/lib/seatschart/models/get_api_workspaces_overview200_response_totals_revenue.rb +238 -0
  35. data/lib/seatschart/models/get_api_workspaces_overview200_response_totals_seats.rb +253 -0
  36. data/lib/seatschart/models/patch_api_events_by_event_id_request.rb +15 -15
  37. data/lib/seatschart/models/patch_api_workspaces_by_workspace_id_keys_by_key_id200_response.rb +221 -0
  38. data/lib/seatschart/models/patch_api_workspaces_by_workspace_id_keys_by_key_id_request.rb +292 -0
  39. data/lib/seatschart/models/patch_api_workspaces_by_workspace_id_request.rb +288 -0
  40. data/lib/seatschart/models/post_api_auth_new_workspace_request.rb +294 -0
  41. data/lib/seatschart/models/post_api_billing_actions_change_plan_request.rb +256 -0
  42. data/lib/seatschart/models/post_api_events_by_event_id_actions_update_extra_data_request_objects_inner.rb +0 -2
  43. data/lib/seatschart/models/post_api_sandboxes201_response.rb +0 -4
  44. data/lib/seatschart/models/post_api_sandboxes_by_sandbox_id_actions_reset200_response.rb +0 -2
  45. data/lib/seatschart/models/post_api_workspaces200_response.rb +464 -0
  46. data/lib/seatschart/models/post_api_workspaces200_response_api_key.rb +332 -0
  47. data/lib/seatschart/models/post_api_workspaces200_response_template.rb +260 -0
  48. data/lib/seatschart/models/post_api_workspaces200_response_template_webhooks_inner.rb +284 -0
  49. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_actions_delete200_response.rb +319 -0
  50. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_actions_delete_request.rb +281 -0
  51. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_invitations201_response.rb +238 -0
  52. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_invitations201_response_invitation.rb +286 -0
  53. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_invitations_request.rb +300 -0
  54. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_keys201_response.rb +237 -0
  55. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_keys201_response_api_key.rb +338 -0
  56. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_keys_request.rb +299 -0
  57. data/lib/seatschart/models/post_api_workspaces_request.rb +100 -4
  58. data/lib/seatschart/models/post_api_workspaces_request_issue_key.rb +294 -0
  59. data/lib/seatschart/version.rb +1 -1
  60. data/lib/seatschart/workspaces.rb +172 -0
  61. data/lib/seatschart.rb +41 -2
  62. metadata +43 -4
  63. data/lib/seatschart/models/put_api_charts_by_chart_id_map_draft_request.rb +0 -349
@@ -0,0 +1,299 @@
1
+ =begin
2
+ #SeatsChart API
3
+
4
+ #Seat inventory and locking API for B2B2C integrations. Authenticate using `x-api-key` (partners) or `Authorization: Bearer` with an HS256 JWT.
5
+
6
+ The version of the OpenAPI document: 1.0.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 SeatsChart
17
+ class PostApiWorkspacesByWorkspaceIdKeysRequest
18
+ attr_accessor :name
19
+
20
+ # Every scope. Default when `scopes` is absent.
21
+ attr_accessor :full_access
22
+
23
+ # Granted scopes: `read`, `holds`, `bookings`, `inventory_admin`, `charts_write`, `events_write`, `reports`, `webhooks`.
24
+ attr_accessor :scopes
25
+
26
+ # Attribute mapping from ruby-style variable name to JSON key.
27
+ def self.attribute_map
28
+ {
29
+ :'name' => :'name',
30
+ :'full_access' => :'fullAccess',
31
+ :'scopes' => :'scopes'
32
+ }
33
+ end
34
+
35
+ # Returns all the JSON keys this model knows about
36
+ def self.acceptable_attributes
37
+ attribute_map.values
38
+ end
39
+
40
+ # Attribute type mapping.
41
+ def self.openapi_types
42
+ {
43
+ :'name' => :'String',
44
+ :'full_access' => :'Boolean',
45
+ :'scopes' => :'Array<String>'
46
+ }
47
+ end
48
+
49
+ # List of attributes with nullable: true
50
+ def self.openapi_nullable
51
+ Set.new([
52
+ ])
53
+ end
54
+
55
+ # Initializes the object
56
+ # @param [Hash] attributes Model attributes in the form of hash
57
+ def initialize(attributes = {})
58
+ if (!attributes.is_a?(Hash))
59
+ fail ArgumentError, "The input argument (attributes) must be a hash in `SeatsChart::PostApiWorkspacesByWorkspaceIdKeysRequest` initialize method"
60
+ end
61
+
62
+ # check to see if the attribute exists and convert string to symbol for hash key
63
+ attributes = attributes.each_with_object({}) { |(k, v), h|
64
+ if (!self.class.attribute_map.key?(k.to_sym))
65
+ fail ArgumentError, "`#{k}` is not a valid attribute in `SeatsChart::PostApiWorkspacesByWorkspaceIdKeysRequest`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
66
+ end
67
+ h[k.to_sym] = v
68
+ }
69
+
70
+ if attributes.key?(:'name')
71
+ self.name = attributes[:'name']
72
+ else
73
+ self.name = nil
74
+ end
75
+
76
+ if attributes.key?(:'full_access')
77
+ self.full_access = attributes[:'full_access']
78
+ end
79
+
80
+ if attributes.key?(:'scopes')
81
+ if (value = attributes[:'scopes']).is_a?(Array)
82
+ self.scopes = value
83
+ end
84
+ end
85
+ end
86
+
87
+ # Show invalid properties with the reasons. Usually used together with valid?
88
+ # @return Array for valid properties with the reasons
89
+ def list_invalid_properties
90
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
91
+ invalid_properties = Array.new
92
+ if @name.nil?
93
+ invalid_properties.push('invalid value for "name", name cannot be nil.')
94
+ end
95
+
96
+ if @name.to_s.length > 256
97
+ invalid_properties.push('invalid value for "name", the character length must be smaller than or equal to 256.')
98
+ end
99
+
100
+ if @name.to_s.length < 1
101
+ invalid_properties.push('invalid value for "name", the character length must be great than or equal to 1.')
102
+ end
103
+
104
+ if !@scopes.nil? && @scopes.length > 16
105
+ invalid_properties.push('invalid value for "scopes", number of items must be less than or equal to 16.')
106
+ end
107
+
108
+ if !@scopes.nil? && @scopes.length < 1
109
+ invalid_properties.push('invalid value for "scopes", number of items must be greater than or equal to 1.')
110
+ end
111
+
112
+ invalid_properties
113
+ end
114
+
115
+ # Check to see if the all the properties in the model are valid
116
+ # @return true if the model is valid
117
+ def valid?
118
+ warn '[DEPRECATED] the `valid?` method is obsolete'
119
+ return false if @name.nil?
120
+ return false if @name.to_s.length > 256
121
+ return false if @name.to_s.length < 1
122
+ return false if !@scopes.nil? && @scopes.length > 16
123
+ return false if !@scopes.nil? && @scopes.length < 1
124
+ true
125
+ end
126
+
127
+ # Custom attribute writer method with validation
128
+ # @param [Object] name Value to be assigned
129
+ def name=(name)
130
+ if name.nil?
131
+ fail ArgumentError, 'name cannot be nil'
132
+ end
133
+
134
+ if name.to_s.length > 256
135
+ fail ArgumentError, 'invalid value for "name", the character length must be smaller than or equal to 256.'
136
+ end
137
+
138
+ if name.to_s.length < 1
139
+ fail ArgumentError, 'invalid value for "name", the character length must be great than or equal to 1.'
140
+ end
141
+
142
+ @name = name
143
+ end
144
+
145
+ # Custom attribute writer method with validation
146
+ # @param [Object] scopes Value to be assigned
147
+ def scopes=(scopes)
148
+ if scopes.nil?
149
+ fail ArgumentError, 'scopes cannot be nil'
150
+ end
151
+
152
+ if scopes.length > 16
153
+ fail ArgumentError, 'invalid value for "scopes", number of items must be less than or equal to 16.'
154
+ end
155
+
156
+ if scopes.length < 1
157
+ fail ArgumentError, 'invalid value for "scopes", number of items must be greater than or equal to 1.'
158
+ end
159
+
160
+ @scopes = scopes
161
+ end
162
+
163
+ # Checks equality by comparing each attribute.
164
+ # @param [Object] Object to be compared
165
+ def ==(o)
166
+ return true if self.equal?(o)
167
+ self.class == o.class &&
168
+ name == o.name &&
169
+ full_access == o.full_access &&
170
+ scopes == o.scopes
171
+ end
172
+
173
+ # @see the `==` method
174
+ # @param [Object] Object to be compared
175
+ def eql?(o)
176
+ self == o
177
+ end
178
+
179
+ # Calculates hash code according to all attributes.
180
+ # @return [Integer] Hash code
181
+ def hash
182
+ [name, full_access, scopes].hash
183
+ end
184
+
185
+ # Builds the object from hash
186
+ # @param [Hash] attributes Model attributes in the form of hash
187
+ # @return [Object] Returns the model itself
188
+ def self.build_from_hash(attributes)
189
+ return nil unless attributes.is_a?(Hash)
190
+ attributes = attributes.transform_keys(&:to_sym)
191
+ transformed_hash = {}
192
+ openapi_types.each_pair do |key, type|
193
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
194
+ transformed_hash["#{key}"] = nil
195
+ elsif type =~ /\AArray<(.*)>/i
196
+ # check to ensure the input is an array given that the attribute
197
+ # is documented as an array but the input is not
198
+ if attributes[attribute_map[key]].is_a?(Array)
199
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
200
+ end
201
+ elsif !attributes[attribute_map[key]].nil?
202
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
203
+ end
204
+ end
205
+ new(transformed_hash)
206
+ end
207
+
208
+ # Deserializes the data based on type
209
+ # @param string type Data type
210
+ # @param string value Value to be deserialized
211
+ # @return [Object] Deserialized data
212
+ def self._deserialize(type, value)
213
+ case type.to_sym
214
+ when :Time
215
+ Time.parse(value)
216
+ when :Date
217
+ Date.parse(value)
218
+ when :String
219
+ value.to_s
220
+ when :Integer
221
+ value.to_i
222
+ when :Float
223
+ value.to_f
224
+ when :Boolean
225
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
226
+ true
227
+ else
228
+ false
229
+ end
230
+ when :Object
231
+ # generic object (usually a Hash), return directly
232
+ value
233
+ when /\AArray<(?<inner_type>.+)>\z/
234
+ inner_type = Regexp.last_match[:inner_type]
235
+ value.map { |v| _deserialize(inner_type, v) }
236
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
237
+ k_type = Regexp.last_match[:k_type]
238
+ v_type = Regexp.last_match[:v_type]
239
+ {}.tap do |hash|
240
+ value.each do |k, v|
241
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
242
+ end
243
+ end
244
+ else # model
245
+ # models (e.g. Pet) or oneOf
246
+ klass = SeatsChart.const_get(type)
247
+ klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
248
+ end
249
+ end
250
+
251
+ # Returns the string representation of the object
252
+ # @return [String] String presentation of the object
253
+ def to_s
254
+ to_hash.to_s
255
+ end
256
+
257
+ # to_body is an alias to to_hash (backward compatibility)
258
+ # @return [Hash] Returns the object in the form of hash
259
+ def to_body
260
+ to_hash
261
+ end
262
+
263
+ # Returns the object in the form of hash
264
+ # @return [Hash] Returns the object in the form of hash
265
+ def to_hash
266
+ hash = {}
267
+ self.class.attribute_map.each_pair do |attr, param|
268
+ value = self.send(attr)
269
+ if value.nil?
270
+ is_nullable = self.class.openapi_nullable.include?(attr)
271
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
272
+ end
273
+
274
+ hash[param] = _to_hash(value)
275
+ end
276
+ hash
277
+ end
278
+
279
+ # Outputs non-array value in the form of hash
280
+ # For object, use to_hash. Otherwise, just return the value
281
+ # @param [Object] value Any valid value
282
+ # @return [Hash] Returns the value in the form of hash
283
+ def _to_hash(value)
284
+ if value.is_a?(Array)
285
+ value.compact.map { |v| _to_hash(v) }
286
+ elsif value.is_a?(Hash)
287
+ {}.tap do |hash|
288
+ value.each { |k, v| hash[k] = _to_hash(v) }
289
+ end
290
+ elsif value.respond_to? :to_hash
291
+ value.to_hash
292
+ else
293
+ value
294
+ end
295
+ end
296
+
297
+ end
298
+
299
+ end
@@ -23,12 +23,23 @@ module SeatsChart
23
23
  # Test workspaces only: copy the current workspace's charts as unpublished drafts (up to 50, archived skipped). Default false.
24
24
  attr_accessor :copy_charts
25
25
 
26
+ # Your own organizer id (letters, digits and `_ . ~ -`), unique among the workspaces you administer: 409 `external_id_taken` names the workspace that has it. Usable in `X-Workspace-Key` and `GET /workspaces/by-external-id/{externalId}`.
27
+ attr_accessor :external_id
28
+
29
+ # A production workspace you administer (id or external id) whose integration settings the new workspace copies: every setting override (pricing source, own catalog, hold period, seats per hold token, ticket buyer validation, GA places to channels, new events not for sale, renderer and draft defaults, buyer extraData), chart validation levels, embed domains (up to the new plan limit) and webhook endpoints (same URL, event types and active flag, each with a NEW signing secret returned once). Not copied: members, API keys, charts, events and the two-factor requirement. 404 `template_not_found` otherwise.
30
+ attr_accessor :template_workspace_id
31
+
32
+ attr_accessor :issue_key
33
+
26
34
  # Attribute mapping from ruby-style variable name to JSON key.
27
35
  def self.attribute_map
28
36
  {
29
37
  :'display_name' => :'displayName',
30
38
  :'is_test' => :'isTest',
31
- :'copy_charts' => :'copyCharts'
39
+ :'copy_charts' => :'copyCharts',
40
+ :'external_id' => :'externalId',
41
+ :'template_workspace_id' => :'templateWorkspaceId',
42
+ :'issue_key' => :'issueKey'
32
43
  }
33
44
  end
34
45
 
@@ -42,7 +53,10 @@ module SeatsChart
42
53
  {
43
54
  :'display_name' => :'String',
44
55
  :'is_test' => :'Boolean',
45
- :'copy_charts' => :'Boolean'
56
+ :'copy_charts' => :'Boolean',
57
+ :'external_id' => :'String',
58
+ :'template_workspace_id' => :'String',
59
+ :'issue_key' => :'PostApiWorkspacesRequestIssueKey'
46
60
  }
47
61
  end
48
62
 
@@ -80,6 +94,18 @@ module SeatsChart
80
94
  if attributes.key?(:'copy_charts')
81
95
  self.copy_charts = attributes[:'copy_charts']
82
96
  end
97
+
98
+ if attributes.key?(:'external_id')
99
+ self.external_id = attributes[:'external_id']
100
+ end
101
+
102
+ if attributes.key?(:'template_workspace_id')
103
+ self.template_workspace_id = attributes[:'template_workspace_id']
104
+ end
105
+
106
+ if attributes.key?(:'issue_key')
107
+ self.issue_key = attributes[:'issue_key']
108
+ end
83
109
  end
84
110
 
85
111
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -99,6 +125,27 @@ module SeatsChart
99
125
  invalid_properties.push('invalid value for "display_name", the character length must be great than or equal to 1.')
100
126
  end
101
127
 
128
+ if !@external_id.nil? && @external_id.to_s.length > 128
129
+ invalid_properties.push('invalid value for "external_id", the character length must be smaller than or equal to 128.')
130
+ end
131
+
132
+ if !@external_id.nil? && @external_id.to_s.length < 1
133
+ invalid_properties.push('invalid value for "external_id", the character length must be great than or equal to 1.')
134
+ end
135
+
136
+ pattern = Regexp.new(/^[A-Za-z0-9_.~-]{1,128}$/)
137
+ if !@external_id.nil? && @external_id !~ pattern
138
+ invalid_properties.push("invalid value for \"external_id\", must conform to the pattern #{pattern}.")
139
+ end
140
+
141
+ if !@template_workspace_id.nil? && @template_workspace_id.to_s.length > 128
142
+ invalid_properties.push('invalid value for "template_workspace_id", the character length must be smaller than or equal to 128.')
143
+ end
144
+
145
+ if !@template_workspace_id.nil? && @template_workspace_id.to_s.length < 1
146
+ invalid_properties.push('invalid value for "template_workspace_id", the character length must be great than or equal to 1.')
147
+ end
148
+
102
149
  invalid_properties
103
150
  end
104
151
 
@@ -109,6 +156,11 @@ module SeatsChart
109
156
  return false if @display_name.nil?
110
157
  return false if @display_name.to_s.length > 512
111
158
  return false if @display_name.to_s.length < 1
159
+ return false if !@external_id.nil? && @external_id.to_s.length > 128
160
+ return false if !@external_id.nil? && @external_id.to_s.length < 1
161
+ return false if !@external_id.nil? && @external_id !~ Regexp.new(/^[A-Za-z0-9_.~-]{1,128}$/)
162
+ return false if !@template_workspace_id.nil? && @template_workspace_id.to_s.length > 128
163
+ return false if !@template_workspace_id.nil? && @template_workspace_id.to_s.length < 1
112
164
  true
113
165
  end
114
166
 
@@ -130,6 +182,47 @@ module SeatsChart
130
182
  @display_name = display_name
131
183
  end
132
184
 
185
+ # Custom attribute writer method with validation
186
+ # @param [Object] external_id Value to be assigned
187
+ def external_id=(external_id)
188
+ if external_id.nil?
189
+ fail ArgumentError, 'external_id cannot be nil'
190
+ end
191
+
192
+ if external_id.to_s.length > 128
193
+ fail ArgumentError, 'invalid value for "external_id", the character length must be smaller than or equal to 128.'
194
+ end
195
+
196
+ if external_id.to_s.length < 1
197
+ fail ArgumentError, 'invalid value for "external_id", the character length must be great than or equal to 1.'
198
+ end
199
+
200
+ pattern = Regexp.new(/^[A-Za-z0-9_.~-]{1,128}$/)
201
+ if external_id !~ pattern
202
+ fail ArgumentError, "invalid value for \"external_id\", must conform to the pattern #{pattern}."
203
+ end
204
+
205
+ @external_id = external_id
206
+ end
207
+
208
+ # Custom attribute writer method with validation
209
+ # @param [Object] template_workspace_id Value to be assigned
210
+ def template_workspace_id=(template_workspace_id)
211
+ if template_workspace_id.nil?
212
+ fail ArgumentError, 'template_workspace_id cannot be nil'
213
+ end
214
+
215
+ if template_workspace_id.to_s.length > 128
216
+ fail ArgumentError, 'invalid value for "template_workspace_id", the character length must be smaller than or equal to 128.'
217
+ end
218
+
219
+ if template_workspace_id.to_s.length < 1
220
+ fail ArgumentError, 'invalid value for "template_workspace_id", the character length must be great than or equal to 1.'
221
+ end
222
+
223
+ @template_workspace_id = template_workspace_id
224
+ end
225
+
133
226
  # Checks equality by comparing each attribute.
134
227
  # @param [Object] Object to be compared
135
228
  def ==(o)
@@ -137,7 +230,10 @@ module SeatsChart
137
230
  self.class == o.class &&
138
231
  display_name == o.display_name &&
139
232
  is_test == o.is_test &&
140
- copy_charts == o.copy_charts
233
+ copy_charts == o.copy_charts &&
234
+ external_id == o.external_id &&
235
+ template_workspace_id == o.template_workspace_id &&
236
+ issue_key == o.issue_key
141
237
  end
142
238
 
143
239
  # @see the `==` method
@@ -149,7 +245,7 @@ module SeatsChart
149
245
  # Calculates hash code according to all attributes.
150
246
  # @return [Integer] Hash code
151
247
  def hash
152
- [display_name, is_test, copy_charts].hash
248
+ [display_name, is_test, copy_charts, external_id, template_workspace_id, issue_key].hash
153
249
  end
154
250
 
155
251
  # Builds the object from hash