zip_money 1.2.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 (124) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +7 -0
  3. data/Gemfile.lock +69 -0
  4. data/README.md +128 -0
  5. data/Rakefile +8 -0
  6. data/docs/Address.md +15 -0
  7. data/docs/Authority.md +9 -0
  8. data/docs/CaptureChargeRequest.md +8 -0
  9. data/docs/Charge.md +17 -0
  10. data/docs/ChargeCollection.md +8 -0
  11. data/docs/ChargeOrder.md +11 -0
  12. data/docs/ChargesApi.md +307 -0
  13. data/docs/Checkout.md +18 -0
  14. data/docs/CheckoutConfiguration.md +8 -0
  15. data/docs/CheckoutFeatures.md +8 -0
  16. data/docs/CheckoutFeaturesTokenisation.md +8 -0
  17. data/docs/CheckoutOrder.md +13 -0
  18. data/docs/CheckoutsApi.md +119 -0
  19. data/docs/CreateChargeRequest.md +14 -0
  20. data/docs/CreateCheckoutRequest.md +13 -0
  21. data/docs/CreateCheckoutRequestFeatures.md +8 -0
  22. data/docs/CreateCheckoutRequestFeaturesTokenisation.md +8 -0
  23. data/docs/CreateRefundRequest.md +11 -0
  24. data/docs/CreateTokenRequest.md +8 -0
  25. data/docs/Customer.md +15 -0
  26. data/docs/CustomersApi.md +96 -0
  27. data/docs/ErrorResponse.md +8 -0
  28. data/docs/ErrorResponseError.md +10 -0
  29. data/docs/ErrorResponseErrorDetails.md +9 -0
  30. data/docs/InlineResponse200.md +8 -0
  31. data/docs/Metadata.md +7 -0
  32. data/docs/OrderItem.md +16 -0
  33. data/docs/OrderShipping.md +10 -0
  34. data/docs/OrderShippingTracking.md +10 -0
  35. data/docs/Refund.md +13 -0
  36. data/docs/RefundsApi.md +181 -0
  37. data/docs/SettlementsApi.md +96 -0
  38. data/docs/Shopper.md +17 -0
  39. data/docs/ShopperStatistics.md +16 -0
  40. data/docs/Token.md +11 -0
  41. data/docs/TokensApi.md +66 -0
  42. data/lib/zip_money.rb +68 -0
  43. data/lib/zip_money/api/charges_api.rb +301 -0
  44. data/lib/zip_money/api/checkouts_api.rb +120 -0
  45. data/lib/zip_money/api/customers_api.rb +116 -0
  46. data/lib/zip_money/api/refunds_api.rb +181 -0
  47. data/lib/zip_money/api/settlements_api.rb +116 -0
  48. data/lib/zip_money/api/tokens_api.rb +70 -0
  49. data/lib/zip_money/api_client.rb +386 -0
  50. data/lib/zip_money/api_error.rb +31 -0
  51. data/lib/zip_money/configuration.rb +238 -0
  52. data/lib/zip_money/models/address.rb +413 -0
  53. data/lib/zip_money/models/authority.rb +235 -0
  54. data/lib/zip_money/models/capture_charge_request.rb +206 -0
  55. data/lib/zip_money/models/charge.rb +369 -0
  56. data/lib/zip_money/models/charge_collection.rb +188 -0
  57. data/lib/zip_money/models/charge_order.rb +250 -0
  58. data/lib/zip_money/models/checkout.rb +344 -0
  59. data/lib/zip_money/models/checkout_configuration.rb +187 -0
  60. data/lib/zip_money/models/checkout_features.rb +181 -0
  61. data/lib/zip_money/models/checkout_features_tokenisation.rb +184 -0
  62. data/lib/zip_money/models/checkout_order.rb +299 -0
  63. data/lib/zip_money/models/create_charge_request.rb +289 -0
  64. data/lib/zip_money/models/create_checkout_request.rb +272 -0
  65. data/lib/zip_money/models/create_checkout_request_features.rb +181 -0
  66. data/lib/zip_money/models/create_checkout_request_features_tokenisation.rb +189 -0
  67. data/lib/zip_money/models/create_refund_request.rb +246 -0
  68. data/lib/zip_money/models/create_token_request.rb +186 -0
  69. data/lib/zip_money/models/customer.rb +310 -0
  70. data/lib/zip_money/models/error_response.rb +181 -0
  71. data/lib/zip_money/models/error_response_error.rb +211 -0
  72. data/lib/zip_money/models/error_response_error_details.rb +190 -0
  73. data/lib/zip_money/models/inline_response_200.rb +188 -0
  74. data/lib/zip_money/models/metadata.rb +172 -0
  75. data/lib/zip_money/models/order_item.rb +333 -0
  76. data/lib/zip_money/models/order_shipping.rb +200 -0
  77. data/lib/zip_money/models/order_shipping_tracking.rb +247 -0
  78. data/lib/zip_money/models/refund.rb +252 -0
  79. data/lib/zip_money/models/shopper.rb +339 -0
  80. data/lib/zip_money/models/shopper_statistics.rb +295 -0
  81. data/lib/zip_money/models/token.rb +228 -0
  82. data/lib/zip_money/version.rb +8 -0
  83. data/spec/api/charges_api_spec.rb +114 -0
  84. data/spec/api/checkouts_api_spec.rb +54 -0
  85. data/spec/api/customers_api_spec.rb +51 -0
  86. data/spec/api/refunds_api_spec.rb +67 -0
  87. data/spec/api/settlements_api_spec.rb +51 -0
  88. data/spec/api/tokens_api_spec.rb +41 -0
  89. data/spec/api_client_spec.rb +219 -0
  90. data/spec/configuration_spec.rb +50 -0
  91. data/spec/models/address_spec.rb +77 -0
  92. data/spec/models/authority_spec.rb +45 -0
  93. data/spec/models/capture_charge_request_spec.rb +35 -0
  94. data/spec/models/charge_collection_spec.rb +35 -0
  95. data/spec/models/charge_order_spec.rb +53 -0
  96. data/spec/models/charge_spec.rb +93 -0
  97. data/spec/models/checkout_configuration_spec.rb +35 -0
  98. data/spec/models/checkout_features_spec.rb +35 -0
  99. data/spec/models/checkout_features_tokenisation_spec.rb +35 -0
  100. data/spec/models/checkout_order_spec.rb +65 -0
  101. data/spec/models/checkout_spec.rb +103 -0
  102. data/spec/models/create_charge_request_spec.rb +75 -0
  103. data/spec/models/create_checkout_request_features_spec.rb +35 -0
  104. data/spec/models/create_checkout_request_features_tokenisation_spec.rb +35 -0
  105. data/spec/models/create_checkout_request_spec.rb +69 -0
  106. data/spec/models/create_refund_request_spec.rb +53 -0
  107. data/spec/models/create_token_request_spec.rb +35 -0
  108. data/spec/models/customer_spec.rb +81 -0
  109. data/spec/models/error_response_error_details_spec.rb +41 -0
  110. data/spec/models/error_response_error_spec.rb +47 -0
  111. data/spec/models/error_response_spec.rb +35 -0
  112. data/spec/models/inline_response_200_spec.rb +35 -0
  113. data/spec/models/metadata_spec.rb +29 -0
  114. data/spec/models/order_item_spec.rb +87 -0
  115. data/spec/models/order_shipping_spec.rb +47 -0
  116. data/spec/models/order_shipping_tracking_spec.rb +47 -0
  117. data/spec/models/refund_spec.rb +65 -0
  118. data/spec/models/shopper_spec.rb +92 -0
  119. data/spec/models/shopper_statistics_spec.rb +86 -0
  120. data/spec/models/token_spec.rb +52 -0
  121. data/spec/payload_helper.rb +96 -0
  122. data/spec/spec_helper.rb +104 -0
  123. data/zip_money.gemspec +38 -0
  124. metadata +380 -0
@@ -0,0 +1,172 @@
1
+ #Merchant API
2
+ #ZipMoney Merchant API Initial build
3
+ #zipMoney Merchant API version: 2017-03-01
4
+
5
+
6
+ require 'date'
7
+
8
+ module ZipMoney
9
+
10
+ class Metadata
11
+
12
+ # Attribute mapping from ruby-style variable name to JSON key.
13
+ def self.attribute_map
14
+ {
15
+ }
16
+ end
17
+
18
+ # Attribute type mapping.
19
+ def self.zip_types
20
+ {
21
+ }
22
+ end
23
+
24
+ # Initializes the object
25
+ # @param [Hash] attributes Model attributes in the form of hash
26
+ def initialize(attributes = {})
27
+ return unless attributes.is_a?(Hash)
28
+
29
+ # convert string to symbol for hash key
30
+ attributes = attributes.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
31
+
32
+ end
33
+
34
+ # Show invalid properties with the reasons. Usually used together with valid?
35
+ # @return Array for valid properies with the reasons
36
+ def list_invalid_properties
37
+ invalid_properties = Array.new
38
+ return invalid_properties
39
+ end
40
+
41
+ # Check to see if the all the properties in the model are valid
42
+ # @return true if the model is valid
43
+ def valid?
44
+ return true
45
+ end
46
+
47
+ # Checks equality by comparing each attribute.
48
+ # @param [Object] Object to be compared
49
+ def ==(o)
50
+ return true if self.equal?(o)
51
+ self.class == o.class
52
+ end
53
+
54
+ # @see the `==` method
55
+ # @param [Object] Object to be compared
56
+ def eql?(o)
57
+ self == o
58
+ end
59
+
60
+ # Calculates hash code according to all attributes.
61
+ # @return [Fixnum] Hash code
62
+ def hash
63
+ [].hash
64
+ end
65
+
66
+ # Builds the object from hash
67
+ # @param [Hash] attributes Model attributes in the form of hash
68
+ # @return [Object] Returns the model itself
69
+ def build_from_hash(attributes)
70
+ return nil unless attributes.is_a?(Hash)
71
+ self.class.zip_types.each_pair do |key, type|
72
+ if type =~ /\AArray<(.*)>/i
73
+ # check to ensure the input is an array given that the the attribute
74
+ # is documented as an array but the input is not
75
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
76
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map{ |v| _deserialize($1, v) } )
77
+ end
78
+ elsif !attributes[self.class.attribute_map[key]].nil?
79
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
80
+ end # or else data not found in attributes(hash), not an issue as the data can be optional
81
+ end
82
+
83
+ self
84
+ end
85
+
86
+ # Deserializes the data based on type
87
+ # @param string type Data type
88
+ # @param string value Value to be deserialized
89
+ # @return [Object] Deserialized data
90
+ def _deserialize(type, value)
91
+ case type.to_sym
92
+ when :DateTime
93
+ DateTime.parse(value)
94
+ when :Date
95
+ Date.parse(value)
96
+ when :String
97
+ value.to_s
98
+ when :Integer
99
+ value.to_i
100
+ when :Float
101
+ value.to_f
102
+ when :BOOLEAN
103
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
104
+ true
105
+ else
106
+ false
107
+ end
108
+ when :Object
109
+ # generic object (usually a Hash), return directly
110
+ value
111
+ when /\AArray<(?<inner_type>.+)>\z/
112
+ inner_type = Regexp.last_match[:inner_type]
113
+ value.map { |v| _deserialize(inner_type, v) }
114
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
115
+ k_type = Regexp.last_match[:k_type]
116
+ v_type = Regexp.last_match[:v_type]
117
+ {}.tap do |hash|
118
+ value.each do |k, v|
119
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
120
+ end
121
+ end
122
+ else # model
123
+ temp_model = ZipMoney.const_get(type).new
124
+ temp_model.build_from_hash(value)
125
+ end
126
+ end
127
+
128
+ # Returns the string representation of the object
129
+ # @return [String] String presentation of the object
130
+ def to_s
131
+ to_hash.to_s
132
+ end
133
+
134
+ # to_body is an alias to to_hash (backward compatibility)
135
+ # @return [Hash] Returns the object in the form of hash
136
+ def to_body
137
+ to_hash
138
+ end
139
+
140
+ # Returns the object in the form of hash
141
+ # @return [Hash] Returns the object in the form of hash
142
+ def to_hash
143
+ hash = {}
144
+ self.class.attribute_map.each_pair do |attr, param|
145
+ value = self.send(attr)
146
+ next if value.nil?
147
+ hash[param] = _to_hash(value)
148
+ end
149
+ hash
150
+ end
151
+
152
+ # Outputs non-array value in the form of hash
153
+ # For object, use to_hash. Otherwise, just return the value
154
+ # @param [Object] value Any valid value
155
+ # @return [Hash] Returns the value in the form of hash
156
+ def _to_hash(value)
157
+ if value.is_a?(Array)
158
+ value.compact.map{ |v| _to_hash(v) }
159
+ elsif value.is_a?(Hash)
160
+ {}.tap do |hash|
161
+ value.each { |k, v| hash[k] = _to_hash(v) }
162
+ end
163
+ elsif value.respond_to? :to_hash
164
+ value.to_hash
165
+ else
166
+ value
167
+ end
168
+ end
169
+
170
+ end
171
+
172
+ end
@@ -0,0 +1,333 @@
1
+ #Merchant API
2
+ #ZipMoney Merchant API Initial build
3
+ #zipMoney Merchant API version: 2017-03-01
4
+
5
+
6
+ require 'date'
7
+
8
+ module ZipMoney
9
+
10
+ class OrderItem
11
+ attr_accessor :name
12
+
13
+ attr_accessor :amount
14
+
15
+ attr_accessor :reference
16
+
17
+ attr_accessor :description
18
+
19
+ attr_accessor :quantity
20
+
21
+ attr_accessor :type
22
+
23
+ attr_accessor :image_uri
24
+
25
+ attr_accessor :item_uri
26
+
27
+ attr_accessor :product_code
28
+
29
+ class EnumAttributeValidator
30
+ attr_reader :datatype
31
+ attr_reader :allowable_values
32
+
33
+ def initialize(datatype, allowable_values)
34
+ @allowable_values = allowable_values.map do |value|
35
+ case datatype.to_s
36
+ when /Integer/i
37
+ value.to_i
38
+ when /Float/i
39
+ value.to_f
40
+ else
41
+ value
42
+ end
43
+ end
44
+ end
45
+
46
+ def valid?(value)
47
+ !value || allowable_values.include?(value)
48
+ end
49
+ end
50
+
51
+ # Attribute mapping from ruby-style variable name to JSON key.
52
+ def self.attribute_map
53
+ {
54
+ :'name' => :'name',
55
+ :'amount' => :'amount',
56
+ :'reference' => :'reference',
57
+ :'description' => :'description',
58
+ :'quantity' => :'quantity',
59
+ :'type' => :'type',
60
+ :'image_uri' => :'image_uri',
61
+ :'item_uri' => :'item_uri',
62
+ :'product_code' => :'product_code'
63
+ }
64
+ end
65
+
66
+ # Attribute type mapping.
67
+ def self.zip_types
68
+ {
69
+ :'name' => :'String',
70
+ :'amount' => :'Float',
71
+ :'reference' => :'String',
72
+ :'description' => :'String',
73
+ :'quantity' => :'Integer',
74
+ :'type' => :'String',
75
+ :'image_uri' => :'String',
76
+ :'item_uri' => :'String',
77
+ :'product_code' => :'String'
78
+ }
79
+ end
80
+
81
+ # Initializes the object
82
+ # @param [Hash] attributes Model attributes in the form of hash
83
+ def initialize(attributes = {})
84
+ return unless attributes.is_a?(Hash)
85
+
86
+ # convert string to symbol for hash key
87
+ attributes = attributes.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
88
+
89
+ if attributes.has_key?(:'name')
90
+ self.name = attributes[:'name']
91
+ end
92
+
93
+ if attributes.has_key?(:'amount')
94
+ self.amount = attributes[:'amount']
95
+ end
96
+
97
+ if attributes.has_key?(:'reference')
98
+ self.reference = attributes[:'reference']
99
+ end
100
+
101
+ if attributes.has_key?(:'description')
102
+ self.description = attributes[:'description']
103
+ end
104
+
105
+ if attributes.has_key?(:'quantity')
106
+ self.quantity = attributes[:'quantity']
107
+ end
108
+
109
+ if attributes.has_key?(:'type')
110
+ self.type = attributes[:'type']
111
+ end
112
+
113
+ if attributes.has_key?(:'image_uri')
114
+ self.image_uri = attributes[:'image_uri']
115
+ end
116
+
117
+ if attributes.has_key?(:'item_uri')
118
+ self.item_uri = attributes[:'item_uri']
119
+ end
120
+
121
+ if attributes.has_key?(:'product_code')
122
+ self.product_code = attributes[:'product_code']
123
+ end
124
+
125
+ end
126
+
127
+ # Show invalid properties with the reasons. Usually used together with valid?
128
+ # @return Array for valid properies with the reasons
129
+ def list_invalid_properties
130
+ invalid_properties = Array.new
131
+ if @name.nil?
132
+ invalid_properties.push("invalid value for 'name', name cannot be nil.")
133
+ end
134
+
135
+ if @amount.nil?
136
+ invalid_properties.push("invalid value for 'amount', amount cannot be nil.")
137
+ end
138
+
139
+ if !@quantity.nil? && @quantity < 1
140
+ invalid_properties.push("invalid value for 'quantity', must be greater than or equal to 1.")
141
+ end
142
+
143
+ if @type.nil?
144
+ invalid_properties.push("invalid value for 'type', type cannot be nil.")
145
+ end
146
+
147
+ if !@product_code.nil? && @product_code.to_s.length > 50
148
+ invalid_properties.push("invalid value for 'product_code', the character length must be smaller than or equal to 50.")
149
+ end
150
+
151
+ return invalid_properties
152
+ end
153
+
154
+ # Check to see if the all the properties in the model are valid
155
+ # @return true if the model is valid
156
+ def valid?
157
+ return false if @name.nil?
158
+ return false if @amount.nil?
159
+ return false if !@quantity.nil? && @quantity < 1
160
+ return false if @type.nil?
161
+ type_validator = EnumAttributeValidator.new('String', ["sku", "tax", "shipping", "discount"])
162
+ return false unless type_validator.valid?(@type)
163
+ return false if !@product_code.nil? && @product_code.to_s.length > 50
164
+ return true
165
+ end
166
+
167
+ # Custom attribute writer method with validation
168
+ # @param [Object] quantity Value to be assigned
169
+ def quantity=(quantity)
170
+
171
+ if !quantity.nil? && quantity < 1
172
+ fail ArgumentError, "invalid value for 'quantity', must be greater than or equal to 1."
173
+ end
174
+
175
+ @quantity = quantity
176
+ end
177
+
178
+ # Custom attribute writer method checking allowed values (enum).
179
+ # @param [Object] type Object to be assigned
180
+ def type=(type)
181
+ validator = EnumAttributeValidator.new('String', ["sku", "tax", "shipping", "discount"])
182
+ unless validator.valid?(type)
183
+ fail ArgumentError, "invalid value for 'type', must be one of #{validator.allowable_values}."
184
+ end
185
+ @type = type
186
+ end
187
+
188
+ # Custom attribute writer method with validation
189
+ # @param [Object] product_code Value to be assigned
190
+ def product_code=(product_code)
191
+
192
+ if !product_code.nil? && product_code.to_s.length > 50
193
+ fail ArgumentError, "invalid value for 'product_code', the character length must be smaller than or equal to 50."
194
+ end
195
+
196
+ @product_code = product_code
197
+ end
198
+
199
+ # Checks equality by comparing each attribute.
200
+ # @param [Object] Object to be compared
201
+ def ==(o)
202
+ return true if self.equal?(o)
203
+ self.class == o.class &&
204
+ name == o.name &&
205
+ amount == o.amount &&
206
+ reference == o.reference &&
207
+ description == o.description &&
208
+ quantity == o.quantity &&
209
+ type == o.type &&
210
+ image_uri == o.image_uri &&
211
+ item_uri == o.item_uri &&
212
+ product_code == o.product_code
213
+ end
214
+
215
+ # @see the `==` method
216
+ # @param [Object] Object to be compared
217
+ def eql?(o)
218
+ self == o
219
+ end
220
+
221
+ # Calculates hash code according to all attributes.
222
+ # @return [Fixnum] Hash code
223
+ def hash
224
+ [name, amount, reference, description, quantity, type, image_uri, item_uri, product_code].hash
225
+ end
226
+
227
+ # Builds the object from hash
228
+ # @param [Hash] attributes Model attributes in the form of hash
229
+ # @return [Object] Returns the model itself
230
+ def build_from_hash(attributes)
231
+ return nil unless attributes.is_a?(Hash)
232
+ self.class.zip_types.each_pair do |key, type|
233
+ if type =~ /\AArray<(.*)>/i
234
+ # check to ensure the input is an array given that the the attribute
235
+ # is documented as an array but the input is not
236
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
237
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map{ |v| _deserialize($1, v) } )
238
+ end
239
+ elsif !attributes[self.class.attribute_map[key]].nil?
240
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
241
+ end # or else data not found in attributes(hash), not an issue as the data can be optional
242
+ end
243
+
244
+ self
245
+ end
246
+
247
+ # Deserializes the data based on type
248
+ # @param string type Data type
249
+ # @param string value Value to be deserialized
250
+ # @return [Object] Deserialized data
251
+ def _deserialize(type, value)
252
+ case type.to_sym
253
+ when :DateTime
254
+ DateTime.parse(value)
255
+ when :Date
256
+ Date.parse(value)
257
+ when :String
258
+ value.to_s
259
+ when :Integer
260
+ value.to_i
261
+ when :Float
262
+ value.to_f
263
+ when :BOOLEAN
264
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
265
+ true
266
+ else
267
+ false
268
+ end
269
+ when :Object
270
+ # generic object (usually a Hash), return directly
271
+ value
272
+ when /\AArray<(?<inner_type>.+)>\z/
273
+ inner_type = Regexp.last_match[:inner_type]
274
+ value.map { |v| _deserialize(inner_type, v) }
275
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
276
+ k_type = Regexp.last_match[:k_type]
277
+ v_type = Regexp.last_match[:v_type]
278
+ {}.tap do |hash|
279
+ value.each do |k, v|
280
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
281
+ end
282
+ end
283
+ else # model
284
+ temp_model = ZipMoney.const_get(type).new
285
+ temp_model.build_from_hash(value)
286
+ end
287
+ end
288
+
289
+ # Returns the string representation of the object
290
+ # @return [String] String presentation of the object
291
+ def to_s
292
+ to_hash.to_s
293
+ end
294
+
295
+ # to_body is an alias to to_hash (backward compatibility)
296
+ # @return [Hash] Returns the object in the form of hash
297
+ def to_body
298
+ to_hash
299
+ end
300
+
301
+ # Returns the object in the form of hash
302
+ # @return [Hash] Returns the object in the form of hash
303
+ def to_hash
304
+ hash = {}
305
+ self.class.attribute_map.each_pair do |attr, param|
306
+ value = self.send(attr)
307
+ next if value.nil?
308
+ hash[param] = _to_hash(value)
309
+ end
310
+ hash
311
+ end
312
+
313
+ # Outputs non-array value in the form of hash
314
+ # For object, use to_hash. Otherwise, just return the value
315
+ # @param [Object] value Any valid value
316
+ # @return [Hash] Returns the value in the form of hash
317
+ def _to_hash(value)
318
+ if value.is_a?(Array)
319
+ value.compact.map{ |v| _to_hash(v) }
320
+ elsif value.is_a?(Hash)
321
+ {}.tap do |hash|
322
+ value.each { |k, v| hash[k] = _to_hash(v) }
323
+ end
324
+ elsif value.respond_to? :to_hash
325
+ value.to_hash
326
+ else
327
+ value
328
+ end
329
+ end
330
+
331
+ end
332
+
333
+ end