chargebee 2.46.0 → 2.47.0.beta.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 23c0cce80dc54db94f1a7b6138751ab2653d66fd
4
- data.tar.gz: 249627e284ea46d5666697acacb34c060326b7cd
2
+ SHA256:
3
+ metadata.gz: 9ba2e9aa886846370aae3bdc348f1bb5b1aa6fc09f80d1b49724078980c13f6e
4
+ data.tar.gz: 6cdeb1bc586bad518cf36f2176fdc1d84a186e88cae3e8761628a8282fd93915
5
5
  SHA512:
6
- metadata.gz: c89c552e4a27ac177cd59ef88ff197c2059f9876971922611350d787d87eddea51b12634a3a356e08b661cea9d0658d9f6a517f67d092a37857cb351253f8595
7
- data.tar.gz: 1aacbfa93badb7b99f7a6b0b18dc2dd3109a999aeaa0efc8a697069f7a80284acbb0087a318f2425e33ee5343b79f83f2a2cdca3f8ba22b37d6cdc6c542f4f6f
6
+ metadata.gz: 9ff62f2371fc2682a0d279dc6457c4da9a5912d3607088dd35d97f34d3e6a9460bdd39b0d5988fdc4808a41ddf3be86c4a71a2b03e944bbd9a93d44b2c28be4c
7
+ data.tar.gz: 292df818217334208d83cfe72b0dc118918db9efb6103a889f56f010e32978d70f3eb251393d424240b6efe851a506f1d94b010f0d89231a852f6c4b654911d2
data/Gemfile.lock CHANGED
@@ -4,7 +4,6 @@ PATH
4
4
  chargebee (2.46.0)
5
5
  cgi (>= 0.1.0, < 1.0.0)
6
6
  json_pure (~> 2.1)
7
- rest-client (>= 1.8, <= 2.0.2)
8
7
 
9
8
  GEM
10
9
  remote: https://rubygems.org/
@@ -21,10 +20,6 @@ GEM
21
20
  mime-types-data (3.2022.0105)
22
21
  mocha (1.13.0)
23
22
  netrc (0.11.0)
24
- rest-client (2.0.2)
25
- http-cookie (>= 1.0.2, < 2.0)
26
- mime-types (>= 1.16, < 4.0)
27
- netrc (~> 0.8)
28
23
  rspec (3.0.0)
29
24
  rspec-core (~> 3.0.0)
30
25
  rspec-expectations (~> 3.0.0)
@@ -43,6 +38,7 @@ GEM
43
38
 
44
39
  PLATFORMS
45
40
  arm64-darwin-21
41
+ arm64-darwin-23
46
42
  x86_64-darwin-20
47
43
  x86_64-linux
48
44
 
data/Rakefile CHANGED
@@ -148,3 +148,16 @@ task :validate do
148
148
  exit!
149
149
  end
150
150
  end
151
+
152
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems for Beta version."
153
+ task :release_beta => :build do
154
+ unless `git branch` =~ /^\* next$/
155
+ puts "You must be on the next branch to release beta!"
156
+ exit!
157
+ end
158
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
159
+ sh "git tag v#{version}"
160
+ sh "git push origin next"
161
+ sh "git push origin v#{version}"
162
+ sh "gem push pkg/#{name}-#{version}.gem"
163
+ end
data/chargebee.gemspec CHANGED
@@ -4,7 +4,7 @@ Gem::Specification.new do |s|
4
4
  s.rubygems_version = '1.3.5'
5
5
  s.required_ruby_version = '>= 1.9.3'
6
6
  s.name = 'chargebee'
7
- s.version = '2.46.0'
7
+ s.version = '2.47.0.beta.1'
8
8
  s.date = '2024-11-14'
9
9
  s.summary = "Ruby client for Chargebee API."
10
10
  s.description = "Subscription Billing - Simple. Secure. Affordable. More details at www.chargebee.com."
@@ -23,7 +23,6 @@ Gem::Specification.new do |s|
23
23
  s.extra_rdoc_files = %w[README.md LICENSE]
24
24
 
25
25
  s.add_dependency('json_pure', '~> 2.1')
26
- s.add_dependency('rest-client', '>=1.8', '<=2.0.2')
27
26
  s.add_dependency('cgi', '>=0.1.0', '<1.0.0')
28
27
  s.add_development_dependency('rspec', '~> 3.0.0')
29
28
  s.add_development_dependency('mocha')
@@ -123,8 +122,8 @@ Gem::Specification.new do |s|
123
122
  lib/chargebee/models/unbilled_charge.rb
124
123
  lib/chargebee/models/usage.rb
125
124
  lib/chargebee/models/virtual_bank_account.rb
125
+ lib/chargebee/nativeRequest.rb
126
126
  lib/chargebee/request.rb
127
- lib/chargebee/rest.rb
128
127
  lib/chargebee/result.rb
129
128
  lib/chargebee/util.rb
130
129
  lib/ssl/ca-certs.crt
@@ -0,0 +1,136 @@
1
+ require 'json'
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'stringio'
5
+
6
+ module ChargeBee
7
+ module NativeRequest
8
+
9
+ def self.request(method, url, env, params = nil, headers = {})
10
+ raise Error.new('No environment configured.') unless env
11
+ api_key = env.api_key
12
+
13
+ uri = URI(env.api_url(url))
14
+
15
+ case method.to_s.downcase.to_sym
16
+ when :get, :head, :delete
17
+ uri.query = URI.encode_www_form(params) if params
18
+ payload = nil
19
+ else
20
+ payload = URI.encode_www_form(params || {})
21
+ end
22
+ user_agent = ChargeBee.user_agent
23
+ headers = {
24
+ "User-Agent" => user_agent,
25
+ "Accept" => "application/json",
26
+ "Lang-Version" => RUBY_VERSION,
27
+ "OS-Version" => RUBY_PLATFORM,
28
+ "Content-Type" => "application/x-www-form-urlencoded"
29
+ }.merge(headers)
30
+
31
+ http = Net::HTTP.new(uri.host, uri.port)
32
+ http.use_ssl = true
33
+ http.open_timeout=env.connect_timeout
34
+ http.read_timeout=env.read_timeout
35
+ if ChargeBee.verify_ca_certs?
36
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
37
+ http.ca_file = ChargeBee.ca_cert_path
38
+ else
39
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
40
+ end
41
+
42
+ request_class = case method.to_s.downcase.to_sym
43
+ when :get then Net::HTTP::Get
44
+ when :post then Net::HTTP::Post
45
+ when :put then Net::HTTP::Put
46
+ when :delete then Net::HTTP::Delete
47
+ else raise Error.new("Unsupported HTTP method: #{method}")
48
+ end
49
+
50
+ request = request_class.new(uri, headers)
51
+ request.body = payload if payload
52
+
53
+ request.basic_auth(api_key, nil)
54
+ begin
55
+ response = http.request(request)
56
+ rescue => e
57
+ raise IOError.new("IO Exception when trying to connect to ChargeBee with URL #{uri} . Reason: #{e}", e)
58
+ end
59
+ handle_response(response, headers)
60
+ end
61
+
62
+ def self.handle_response(response, headers)
63
+ rcode = response.code.to_i
64
+ rbody = response.body
65
+
66
+ # converting headers to rest-client format previously we were using rest-client,
67
+ # and mapping headers to that format to support backward compatability
68
+ rheaders = beautify_headers(response.to_hash)
69
+
70
+ # When a custom 'Accept-Encoding' header is set to gzip, Net::HTTP will not automatically
71
+ # decompress the response. Therefore, we need to manually handle decompression
72
+ # based on the 'Content-Encoding' header in the response.
73
+ # https://github.com/ruby/ruby/blob/19c1f0233eb5202403c52b196f1d573893eacab7/lib/net/http/generic_request.rb#L82
74
+ if headers.keys.any? { |k| k.downcase == 'accept-encoding' } && rheaders[:content_encoding] == 'gzip' && rbody && !rbody.empty?
75
+ rbody = Zlib::GzipReader.new(StringIO.new(rbody)).read
76
+ end
77
+
78
+ if rcode >= 200 && rcode < 300
79
+ begin
80
+ resp = JSON.parse(rbody)
81
+ rescue JSON::ParserError => e
82
+ raise handle_json_error(rbody, e)
83
+ end
84
+ return Util.symbolize_keys(resp), rheaders
85
+ else
86
+ raise handle_for_error(rcode, rbody)
87
+ end
88
+ end
89
+
90
+ def self.handle_json_error(rbody, e)
91
+ if rbody.include?("503")
92
+ raise Error.new("Sorry, the server is currently unable to handle the request due to a temporary overload or scheduled maintenance. Please retry after sometime. \n type: internal_temporary_error, \n http_status_code: 503, \n error_code: internal_temporary_error,\n content: #{rbody.inspect}",e)
93
+ elsif rbody.include?("504")
94
+ raise Error.new("The server did not receive a timely response from an upstream server, request aborted. If this problem persists, contact us at support@chargebee.com. \n type: gateway_timeout, \n http_status_code: 504, \n error_code: gateway_timeout,\n content: #{rbody.inspect}",e)
95
+ else
96
+ raise Error.new("Sorry, something went wrong when trying to process the request. If this problem persists, contact us at support@chargebee.com. \n type: internal_error, \n http_status_code: 500, \n error_code: internal_error,\n content: #{rbody.inspect}",e)
97
+ end
98
+ end
99
+
100
+ def self.handle_for_error(rcode, rbody)
101
+ return Error.new("No response returned by ChargeBee API. HTTP status code: #{rcode}") if rcode == 204
102
+ begin
103
+ error_obj = JSON.parse(rbody)
104
+ error_obj = Util.symbolize_keys(error_obj)
105
+ rescue Exception => e
106
+ raise Error.new("Error response not in JSON format. The http status code is #{rcode} \n #{rbody.inspect}",e)
107
+ end
108
+ type = error_obj[:type]
109
+ case type
110
+ when "payment"
111
+ raise PaymentError.new(rcode, error_obj)
112
+ when "operation_failed"
113
+ raise OperationFailedError.new(rcode, error_obj)
114
+ when "invalid_request"
115
+ raise InvalidRequestError.new(rcode, error_obj)
116
+ else
117
+ raise APIError.new(rcode, error_obj)
118
+ end
119
+ end
120
+ # directly copying headers formatting from rest-client to support backward compatability for rest-client
121
+ def self.beautify_headers(headers)
122
+ headers.inject({}) do |out, (key, value)|
123
+ key_sym = key.tr('-', '_').downcase.to_sym
124
+
125
+ # Handle Set-Cookie specially since it cannot be joined by comma.
126
+ if key.downcase == 'set-cookie'
127
+ out[key_sym] = value
128
+ else
129
+ out[key_sym] = value.join(', ')
130
+ end
131
+
132
+ out
133
+ end
134
+ end
135
+ end
136
+ end
@@ -15,7 +15,7 @@ module ChargeBee
15
15
  def self.send(method, url, params={}, env=nil, headers={})
16
16
  env ||= ChargeBee.default_env
17
17
  ser_params = Util.serialize(params)
18
- resp, rheaders = Rest.request(method, url, env, ser_params||={}, headers)
18
+ resp, rheaders = NativeRequest.request(method, url, env, ser_params||={}, headers)
19
19
  if resp.has_key?(:list)
20
20
  ListResult.new(resp[:list], resp[:next_offset], rheaders)
21
21
  else
data/lib/chargebee.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/chargebee/environment'
2
- require File.dirname(__FILE__) + '/chargebee/rest'
2
+ require File.dirname(__FILE__) + '/chargebee/nativeRequest'
3
3
  require File.dirname(__FILE__) + '/chargebee/util'
4
4
  require File.dirname(__FILE__) + '/chargebee/request'
5
5
  require File.dirname(__FILE__) + '/chargebee/result'
@@ -86,7 +86,7 @@ require File.dirname(__FILE__) + '/chargebee/models/recorded_purchase'
86
86
 
87
87
  module ChargeBee
88
88
 
89
- VERSION = '2.46.0'
89
+ VERSION = '2.47.0.beta.1'
90
90
 
91
91
  @@default_env = nil
92
92
  @@verify_ca_certs = true
@@ -43,7 +43,7 @@ describe ChargeBee::ListResult do
43
43
  end
44
44
 
45
45
  before do
46
- ChargeBee::Rest.stubs(:request).returns(response)
46
+ ChargeBee::NativeRequest.stubs(:request).returns(response)
47
47
  end
48
48
 
49
49
  it "returns list object, with next offset attribute" do
@@ -1,11 +1,10 @@
1
1
  require 'spec_helper'
2
- require 'rest_client'
3
2
  require 'sample_response'
4
3
 
5
4
  describe "chargebee" do
6
5
 
7
6
  before(:all) do
8
- @request = RestClient::Request
7
+ @request = ChargeBee::NativeRequest
9
8
  end
10
9
 
11
10
  it "serialize should convert the hash to acceptable format" do
@@ -55,7 +54,7 @@ describe "chargebee" do
55
54
  end
56
55
 
57
56
  it "should properly convert the response json into proper object" do
58
- @request.expects(:execute).once.returns(mock_response(simple_subscription, headers))
57
+ @request.expects(:request).once.returns([simple_subscription, headers])
59
58
  result = ChargeBee::Subscription.retrieve("simple_subscription")
60
59
  h = result.get_response_headers
61
60
  expect(h).to eq(headers)
@@ -68,7 +67,7 @@ describe "chargebee" do
68
67
  end
69
68
 
70
69
  it "should properly convert the nested response json into proper object with sub types" do
71
- @request.expects(:execute).once.returns(mock_response(nested_subscription, headers))
70
+ @request.expects(:request).once.returns([nested_subscription, headers])
72
71
  result = ChargeBee::Subscription.retrieve("nested_subscription")
73
72
  s = result.subscription
74
73
  expect(s.id).to eq("nested_subscription")
@@ -80,7 +79,7 @@ describe "chargebee" do
80
79
  end
81
80
 
82
81
  it "should properly convert the list response json into proper result object" do
83
- @request.expects(:execute).once.returns(mock_response(list_subscriptions, headers))
82
+ @request.expects(:request).once.returns([list_subscriptions, headers])
84
83
  result = ChargeBee::Subscription.list({:limit => 2})
85
84
  expect(result.length).to eq(2)
86
85
  result.each do |i|
@@ -89,7 +88,7 @@ describe "chargebee" do
89
88
  end
90
89
 
91
90
  it "should parse event api response and provide the content properly" do
92
- @request.expects(:execute).once.returns(mock_response(sample_event, headers))
91
+ @request.expects(:request).once.returns([sample_event, headers])
93
92
  result = ChargeBee::Event.retrieve("sample_event")
94
93
  event = result.event
95
94
  s = event.content.subscription
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chargebee
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.46.0
4
+ version: 2.47.0.beta.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rajaraman S
8
8
  - Thiyagarajan T
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
  date: 2024-11-14 00:00:00.000000000 Z
@@ -15,82 +15,62 @@ dependencies:
15
15
  name: json_pure
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: '2.1'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ~>
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '2.1'
28
- - !ruby/object:Gem::Dependency
29
- name: rest-client
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - '>='
33
- - !ruby/object:Gem::Version
34
- version: '1.8'
35
- - - <=
36
- - !ruby/object:Gem::Version
37
- version: 2.0.2
38
- type: :runtime
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- requirements:
42
- - - '>='
43
- - !ruby/object:Gem::Version
44
- version: '1.8'
45
- - - <=
46
- - !ruby/object:Gem::Version
47
- version: 2.0.2
48
28
  - !ruby/object:Gem::Dependency
49
29
  name: cgi
50
30
  requirement: !ruby/object:Gem::Requirement
51
31
  requirements:
52
- - - '>='
32
+ - - ">="
53
33
  - !ruby/object:Gem::Version
54
34
  version: 0.1.0
55
- - - <
35
+ - - "<"
56
36
  - !ruby/object:Gem::Version
57
37
  version: 1.0.0
58
38
  type: :runtime
59
39
  prerelease: false
60
40
  version_requirements: !ruby/object:Gem::Requirement
61
41
  requirements:
62
- - - '>='
42
+ - - ">="
63
43
  - !ruby/object:Gem::Version
64
44
  version: 0.1.0
65
- - - <
45
+ - - "<"
66
46
  - !ruby/object:Gem::Version
67
47
  version: 1.0.0
68
48
  - !ruby/object:Gem::Dependency
69
49
  name: rspec
70
50
  requirement: !ruby/object:Gem::Requirement
71
51
  requirements:
72
- - - ~>
52
+ - - "~>"
73
53
  - !ruby/object:Gem::Version
74
54
  version: 3.0.0
75
55
  type: :development
76
56
  prerelease: false
77
57
  version_requirements: !ruby/object:Gem::Requirement
78
58
  requirements:
79
- - - ~>
59
+ - - "~>"
80
60
  - !ruby/object:Gem::Version
81
61
  version: 3.0.0
82
62
  - !ruby/object:Gem::Dependency
83
63
  name: mocha
84
64
  requirement: !ruby/object:Gem::Requirement
85
65
  requirements:
86
- - - '>='
66
+ - - ">="
87
67
  - !ruby/object:Gem::Version
88
68
  version: '0'
89
69
  type: :development
90
70
  prerelease: false
91
71
  version_requirements: !ruby/object:Gem::Requirement
92
72
  requirements:
93
- - - '>='
73
+ - - ">="
94
74
  - !ruby/object:Gem::Version
95
75
  version: '0'
96
76
  description: Subscription Billing - Simple. Secure. Affordable. More details at www.chargebee.com.
@@ -196,8 +176,8 @@ files:
196
176
  - lib/chargebee/models/unbilled_charge.rb
197
177
  - lib/chargebee/models/usage.rb
198
178
  - lib/chargebee/models/virtual_bank_account.rb
179
+ - lib/chargebee/nativeRequest.rb
199
180
  - lib/chargebee/request.rb
200
- - lib/chargebee/rest.rb
201
181
  - lib/chargebee/result.rb
202
182
  - lib/chargebee/util.rb
203
183
  - lib/ssl/ca-certs.crt
@@ -211,25 +191,24 @@ licenses:
211
191
  - MIT
212
192
  metadata:
213
193
  changelog_uri: https://github.com/chargebee/chargebee-ruby/blob/master/CHANGELOG.md
214
- post_install_message:
194
+ post_install_message:
215
195
  rdoc_options:
216
- - --charset=UTF-8
196
+ - "--charset=UTF-8"
217
197
  require_paths:
218
198
  - lib
219
199
  required_ruby_version: !ruby/object:Gem::Requirement
220
200
  requirements:
221
- - - '>='
201
+ - - ">="
222
202
  - !ruby/object:Gem::Version
223
203
  version: 1.9.3
224
204
  required_rubygems_version: !ruby/object:Gem::Requirement
225
205
  requirements:
226
- - - '>='
206
+ - - ">="
227
207
  - !ruby/object:Gem::Version
228
208
  version: '0'
229
209
  requirements: []
230
- rubyforge_project:
231
- rubygems_version: 2.4.5
232
- signing_key:
210
+ rubygems_version: 3.5.9
211
+ signing_key:
233
212
  specification_version: 2
234
213
  summary: Ruby client for Chargebee API.
235
214
  test_files:
@@ -1,99 +0,0 @@
1
- require 'rest_client'
2
- require 'json'
3
-
4
- module ChargeBee
5
- module Rest
6
-
7
- def self.request(method, url, env, params=nil, headers={})
8
- raise Error.new('No environment configured.') unless env
9
- api_key = env.api_key
10
-
11
- if(ChargeBee.verify_ca_certs?)
12
- ssl_opts = {
13
- :verify_ssl => OpenSSL::SSL::VERIFY_PEER,
14
- :ssl_ca_file => ChargeBee.ca_cert_path
15
- }
16
- else
17
- ssl_opts = {
18
- :verify_ssl => false
19
- }
20
- end
21
- case method.to_s.downcase.to_sym
22
- when :get, :head, :delete
23
- headers = { :params => params }.merge(headers)
24
- payload = nil
25
- else
26
- payload = params
27
- end
28
-
29
- user_agent = ChargeBee.user_agent
30
- headers = {
31
- "User-Agent" => user_agent,
32
- :accept => :json,
33
- "Lang-Version" => RUBY_VERSION,
34
- "OS-Version" => RUBY_PLATFORM
35
- }.merge(headers)
36
- opts = {
37
- :method => method,
38
- :url => env.api_url(url),
39
- :user => api_key,
40
- :headers => headers,
41
- :payload => payload,
42
- :open_timeout => env.connect_timeout,
43
- :timeout => env.read_timeout
44
- }.merge(ssl_opts)
45
-
46
- begin
47
- response = RestClient::Request.execute(opts)
48
- rescue RestClient::ExceptionWithResponse => e
49
- if rcode = e.http_code and rbody = e.http_body
50
- raise handle_for_error(e, rcode, rbody)
51
- else
52
- raise IOError.new("IO Exception when trying to connect to chargebee with url #{opts[:url]} . Reason #{e}",e)
53
- end
54
- rescue Exception => e
55
- raise IOError.new("IO Exception when trying to connect to chargebee with url #{opts[:url]} . Reason #{e}",e)
56
- end
57
- rheaders = response.headers
58
- rbody = response.body
59
- rcode = response.code
60
- begin
61
- resp = JSON.parse(rbody)
62
- rescue Exception => e
63
- if rbody.include? "503"
64
- raise Error.new("Sorry, the server is currently unable to handle the request due to a temporary overload or scheduled maintenance. Please retry after sometime. \n type: internal_temporary_error, \n http_status_code: 503, \n error_code: internal_temporary_error,\n content: #{rbody.inspect}",e)
65
- elsif rbody.include? "504"
66
- raise Error.new("The server did not receive a timely response from an upstream server, request aborted. If this problem persists, contact us at support@chargebee.com. \n type: gateway_timeout, \n http_status_code: 504, \n error_code: gateway_timeout,\n content: #{rbody.inspect}",e)
67
- else
68
- raise Error.new("Sorry, something went wrong when trying to process the request. If this problem persists, contact us at support@chargebee.com. \n type: internal_error, \n http_status_code: 500, \n error_code: internal_error,\n content: #{rbody.inspect}",e)
69
- end
70
- end
71
- resp = Util.symbolize_keys(resp)
72
- return resp, rheaders
73
- end
74
-
75
- def self.handle_for_error(e, rcode=nil, rbody=nil)
76
- if(rcode == 204)
77
- raise Error.new("No response returned by the chargebee api. The http status code is #{rcode}")
78
- end
79
- begin
80
- error_obj = JSON.parse(rbody)
81
- error_obj = Util.symbolize_keys(error_obj)
82
- rescue Exception => e
83
- raise Error.new("Error response not in JSON format. The http status code is #{rcode} \n #{rbody.inspect}",e)
84
- end
85
- type = error_obj[:type]
86
- if("payment" == type)
87
- raise PaymentError.new(rcode, error_obj)
88
- elsif("operation_failed" == type)
89
- raise OperationFailedError.new(rcode, error_obj)
90
- elsif("invalid_request" == type)
91
- raise InvalidRequestError.new(rcode, error_obj)
92
- else
93
- raise APIError.new(rcode, error_obj)
94
- end
95
-
96
- end
97
-
98
- end
99
- end