app_manager 1.2.5 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,7 +33,7 @@ module AppManager
33
33
  response = ActiveSupport::JSON.decode(response.read_body) rescue nil
34
34
  return response
35
35
  else
36
- Rails.logger.info "=== params missing from any of these api_key, api_version, shopify_domain, shopify_token ==="
36
+ Rollbar.error("=== params missing from any of these api_key, api_version, shopify_domain, shopify_token ===")
37
37
  return []
38
38
  end
39
39
  end
@@ -61,10 +61,8 @@ module AppManager
61
61
  trial_days = plan['trial_days'] || 0
62
62
 
63
63
  if shop && shop.shopify_domain && trial_days
64
- trial_activated_at_field = AppManager.configuration.field_names['trial_activated_at'] rescue nil
65
- trial_activated_at = shop[trial_activated_at] rescue nil
66
- plan_field = AppManager.configuration.plan_id_or_name_field rescue nil
67
- plan_id_field = shop[@plan_field] rescue nil
64
+ trial_activated_at = shop[AppManager.configuration.field_names['trial_activated_at']] rescue nil
65
+ plan_id_field = shop[AppManager.configuration.plan_id_or_name_field] rescue nil
68
66
  remaining_obj = AppManager::Client.new
69
67
  remaining = remaining_obj.get_remaining_days(shop.shopify_domain,trial_activated_at,plan_id_field)
70
68
  trial_days = !remaining.nil? ? remaining : trial_days
@@ -2,259 +2,258 @@ module AppManager
2
2
  module Model
3
3
  extend ActiveSupport::Concern
4
4
 
5
- @@remaining_cache_key = "get_remaining_days_key"
6
- @@get_charge_key = "get_charge_key"
5
+ def has_plan_old
6
+ if !self[AppManager.configuration.plan_id_or_name_field]
7
+ return false;
8
+ end
9
+ if self[AppManager.configuration.field_names['grandfathered']]
10
+ return true;
11
+ end
12
+ plan_id = self[AppManager.configuration.plan_id_or_name_field]
13
+ if !plan_id
14
+ return false;
15
+ end
16
+ remaining_days = fetch_static_remaining_days
17
+ if remaining_days.to_i > 0
18
+ return true
19
+ end
20
+ # plan_obj = AppManager::Client.new
21
+ # shop_domain = self[AppManager.configuration.shopify_domain_field]
22
+ # active_charge = plan_obj.get_charge(shop_domain) rescue nil
23
+ active_charge = fetch_static_get_charge
24
+ return active_charge && active_charge['active_charge'].present? && !active_charge['active_charge'].nil? ? true : false
25
+ end
7
26
 
8
27
  def has_plan
9
- if !self[AppManager.configuration.plan_id_or_name_field]
10
- return false;
11
- end
12
- if self[AppManager.configuration.field_names['grandfathered']]
13
- return true;
14
- end
15
- plan_id = self[AppManager.configuration.plan_id_or_name_field]
16
- if !plan_id
17
- Rails.logger.info "Plan id found nil or not set"
18
- return false;
19
- end
20
- remaining_days = fetch_static_remaining_days
21
- if remaining_days > 0
22
- return true
23
- end
24
- # plan_obj = AppManager::Client.new
25
- # shop_domain = self[AppManager.configuration.shopify_domain_field]
26
- # active_charge = plan_obj.get_charge(shop_domain) rescue nil
27
- active_charge = fetch_static_get_charge
28
- return active_charge && active_charge['active_charge'].present? && !active_charge['active_charge'].nil? ? true : false
28
+ plan_id = self[AppManager.configuration.plan_id_or_name_field]
29
+ if !plan_id
30
+ return false;
31
+ end
32
+ grandfathered = self[AppManager.configuration.field_names['grandfathered']]
33
+ grandfathered = grandfathered ? 1 : 0
34
+ shop_domain = self[AppManager.configuration.shopify_domain_field] rescue nil
35
+ trial_activated_at_val = self[AppManager.configuration.field_names['trial_activated_at']] rescue nil
36
+ plan_obj = AppManager::Client.new
37
+ response = plan_obj.has_plan(shop_domain, plan_id, trial_activated_at_val, grandfathered)
38
+ return (response && response['has_plan']) || false
29
39
  end
30
40
 
31
41
 
32
-
33
42
  def plan_features
34
- plan_id = self[AppManager.configuration.plan_id_or_name_field]
35
- if !plan_id
36
- Rails.logger.info "Plan id found nil or not set in DB"
37
- return []
38
- end
39
- plan_obj = AppManager::Client.new
40
- plans = plan_obj.get_plan(plan_id)
41
- if plans && plans['features'].blank?
42
- return []
43
- end
44
- features_by_plan = plans['features'].map { |h| h.slice('value', 'feature_id') }
45
- all_features = AppManager.configuration.plan_features
46
- feature_plan_ids = features_by_plan.map{|c| c['feature_id']}
47
- pf = all_features.select{|x| feature_plan_ids.include?(x['uuid'])}.each{|g| g["value"] = features_by_plan.find{|e| e['feature_id'] == g['uuid']}['value'] }
48
- return pf
43
+ plan_id = self[AppManager.configuration.plan_id_or_name_field]
44
+ if !plan_id
45
+ return []
46
+ end
47
+ plan_obj = AppManager::Client.new
48
+ plans = plan_obj.get_plan(plan_id)
49
+ if plans && plans['features'].blank?
50
+ return []
51
+ end
52
+ features_by_plan = plans['features'].map { |h| h.slice('value', 'feature_id') }
53
+ all_features = AppManager.configuration.plan_features
54
+ feature_plan_ids = features_by_plan.map { |c| c['feature_id'] }
55
+ pf = all_features.select { |x| feature_plan_ids.include?(x['uuid']) }.each { |g| g["value"] = features_by_plan.find { |e| e['feature_id'] == g['uuid'] }['value'] }
56
+ return pf
49
57
  end
50
58
 
51
59
 
52
-
53
60
  def has_feature(slug)
54
- self.plan_features.select{|x| x['slug'].to_s == slug }.size > 0
61
+ self.plan_features.any? && self.plan_features.select { |x| x['slug'].to_s == slug }.size > 0 ? true : false
55
62
  end
56
63
 
57
64
 
58
65
  def get_feature(slug)
59
- plan_features = self.plan_features
60
- features = plan_features.select{|x| x['slug'].to_s == slug }
61
- if features.any?
62
- feature = features.first
63
- return casted_value(feature['value'],feature['value_type'])
64
- else
65
- nil
66
- end
66
+ plan_features = self.plan_features
67
+ features = plan_features.select { |x| x['slug'].to_s == slug }
68
+ if features.any?
69
+ feature = features.first
70
+ return casted_value(feature['value'], feature['value_type'])
71
+ else
72
+ nil
73
+ end
67
74
  end
68
75
 
69
76
  def get_remaining_days
70
- begin
71
- shop_domain = self[AppManager.configuration.shopify_domain_field]
72
- trial_activated_at_field = AppManager.configuration.field_names['trial_activated_at']
73
- trial_activated_at_val = self[trial_activated_at_field]
74
- plan_field = AppManager.configuration.field_names['plan_id']
75
- plan_id = self[plan_field]
76
- plan_obj = AppManager::Client.new
77
- return shop_domain ? plan_obj.get_remaining_days(shop_domain,trial_activated_at_val,plan_id) : 0
78
- rescue Exception => e
79
- return "#{e.inspect}"
80
- end
77
+ begin
78
+ shop_domain = self[AppManager.configuration.shopify_domain_field]
79
+ trial_activated_at_field = AppManager.configuration.field_names['trial_activated_at']
80
+ trial_activated_at_val = self[trial_activated_at_field]
81
+ plan_field = AppManager.configuration.field_names['plan_id']
82
+ plan_id = self[plan_field]
83
+ plan_obj = AppManager::Client.new
84
+ res = plan_obj.get_remaining_days(shop_domain, trial_activated_at_val, plan_id)
85
+ return (res && !res.nil?) ? res : 0
86
+ rescue Exception => e
87
+ Rollbar.error("APP MANAGER Get Remaining Days Failed #{e}")
88
+ end
81
89
  end
82
90
 
83
91
 
84
- def get_plan(plan_id=nil)
85
- req_plan_id = nil
86
- if !plan_id.nil?
87
- req_plan_id = plan_id
92
+ def get_plan(plan_id = nil)
93
+ req_plan_id = nil
94
+ if !plan_id.nil?
95
+ req_plan_id = plan_id
96
+ else
97
+ shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
98
+ if shop_plan_id && !shop_plan_id.nil?
99
+ req_plan_id = shop_plan_id
88
100
  else
89
- shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
90
- if shop_plan_id && !shop_plan_id.nil?
91
- req_plan_id = shop_plan_id
92
- else
93
- Rails.logger.info "Invalid params, must have charge_id,shop && plan"
94
- return {}
95
- end
101
+ Rollbar.error("Invalid params, must have charge_id,shop && plan")
102
+ return {}
96
103
  end
97
- plan_obj = AppManager::Client.new if req_plan_id
98
- return req_plan_id ? plan_obj.get_plan(req_plan_id) : {}
104
+ end
105
+ plan_obj = AppManager::Client.new if req_plan_id
106
+ return req_plan_id ? plan_obj.get_plan(req_plan_id) : {}
99
107
  end
100
108
 
101
109
  def get_charge
102
- shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
103
- found_free_plan = false
104
- if shop_plan_id && !shop_plan_id.nil?
105
- plan_obj = AppManager::Client.new
106
- plan = plan_obj.get_plan(shop_plan_id) rescue nil
107
- if plan && plan['price'] == 0 && plan['public'] == true
108
- found_free_plan = true
109
- return nil
110
- end
110
+ shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
111
+ found_free_plan = false
112
+ if shop_plan_id && !shop_plan_id.nil?
113
+ plan_obj = AppManager::Client.new
114
+ plan = plan_obj.get_plan(shop_plan_id) rescue nil
115
+ if plan && plan['price'] == 0 && plan['public'] == true
116
+ found_free_plan = true
117
+ return nil
111
118
  end
112
- if !found_free_plan
113
- begin
114
- shop_domain = self[AppManager.configuration.shopify_domain_field]
115
- plan_obj = AppManager::Client.new
116
- return plan_obj.get_charge(shop_domain)
117
- rescue Exception => e
118
- Rails.logger.info "#{e.inspect}"
119
- return nil
120
- end
119
+ end
120
+ if !found_free_plan
121
+ begin
122
+ shop_domain = self[AppManager.configuration.shopify_domain_field]
123
+ plan_obj = AppManager::Client.new
124
+ return plan_obj.get_charge(shop_domain)
125
+ rescue Exception => e
126
+ return nil
121
127
  end
128
+ end
122
129
  end
123
130
 
124
131
  def get_all_plans
125
- begin
126
- shop_domain = self[AppManager.configuration.shopify_domain_field]
127
- shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
128
- active_plan_id = shop_plan_id && shop_plan_id.nil? ? nil : shop_plan_id
129
- plan_obj = AppManager::Client.new
130
- return plan_obj.get_plans(shop_domain,active_plan_id)
131
- rescue Exception => e
132
- Rails.logger.info "#{e.inspect}"
133
- return []
134
- end
132
+ begin
133
+ shop_domain = self[AppManager.configuration.shopify_domain_field]
134
+ shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
135
+ active_plan_id = shop_plan_id && shop_plan_id.nil? ? nil : shop_plan_id
136
+ plan_obj = AppManager::Client.new
137
+ return plan_obj.get_plans(shop_domain, active_plan_id)
138
+ rescue Exception => e
139
+ return []
140
+ end
135
141
  end
136
142
 
137
143
  def cancel_charge
138
- begin
139
- shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
140
- shop_domain = self[AppManager.configuration.shopify_domain_field]
141
- if shop_plan_id && shop_domain
142
- plan_obj = AppManager::Client.new
143
- plan_obj.cancel_charge(shop_domain,shop_plan_id)
144
- end
145
- rescue Exception => e
146
- return "#{e.inspect}"
147
- end
144
+ begin
145
+ shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
146
+ shop_domain = self[AppManager.configuration.shopify_domain_field]
147
+ if shop_plan_id && shop_domain
148
+ plan_obj = AppManager::Client.new
149
+ plan_obj.cancel_charge(shop_domain, shop_plan_id)
150
+ end
151
+ rescue Exception => e
152
+ return "#{e.inspect}"
153
+ end
148
154
  end
149
155
 
150
- def set_default_plan(plan_id=nil)
151
- begin
152
- if plan_id.nil?
153
- shop_domain = self[AppManager.configuration.shopify_domain_field]
154
- plan_obj = AppManager::Client.new
155
- plans = plan_obj.get_plans(shop_domain)
156
- free_plans = plans.select{|x| x['price'] == 0 && x['public'] == true}
157
- if free_plans.any?
158
- self.plan_id = free_plans.first["id"]
159
- self.save
160
- else
161
- raise Error, "Free Plan is not available"
162
- end
163
- else
164
- self.plan_id = plan_id
165
- self.save
166
- end
167
- rescue Exception => e
168
- return "#{e.inspect}"
156
+ def set_default_plan(plan_id = nil)
157
+ begin
158
+ if plan_id.nil?
159
+ shop_domain = self[AppManager.configuration.shopify_domain_field]
160
+ plan_obj = AppManager::Client.new
161
+ plans = plan_obj.get_plans(shop_domain)
162
+ free_plans = plans.select { |x| x['price'] == 0 && x['public'] == true }
163
+ if free_plans.any?
164
+ self.plan_id = free_plans.first["id"]
165
+ self.save
166
+ else
167
+ raise Error, "Free Plan is not available"
168
+ end
169
+ else
170
+ self.plan_id = plan_id
171
+ self.save
169
172
  end
173
+ rescue Exception => e
174
+ return "#{e.inspect}"
175
+ end
170
176
  end
171
177
 
172
178
 
173
-
174
-
175
- def get_plans_by_features(feature_slugs,params="false")
176
- if feature_slugs.any?
177
- shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
178
- plan_data = []
179
- shop_domain = self[AppManager.configuration.shopify_domain_field]
180
- plan_obj = AppManager::Client.new
181
- plans = plan_obj.get_plans(shop_domain)
182
- plans = plans.select{|x| x['interval'] == 'EVERY_30_DAYS' && x['public'] == true}
183
- plans.each do |plan|
184
- next if (params && !params.nil? && params == "exclude_current_plan" && !shop_plan_id.nil? && plan["id"] == shop_plan_id)
185
- if plan && (plan['features'] && plan['features'].any?) && (plan['features'].values && plan['features'].values.any?) && (plan['features'].values.collect{|c| c['slug']} && plan['features'].values.collect{|c| c['slug']}.any?)
186
- plan_feature_slugs = plan['features'].values.collect{|c| c['slug']}.sort
187
- if (feature_slugs & plan_feature_slugs).any? && ((feature_slugs & plan_feature_slugs).sort == feature_slugs.sort)
188
- plan_data.push(plan)
189
- end
190
- end
179
+ def get_plans_by_features(feature_slugs, params = "false")
180
+ if feature_slugs.any?
181
+ shop_plan_id = self[AppManager.configuration.plan_id_or_name_field]
182
+ plan_data = []
183
+ shop_domain = self[AppManager.configuration.shopify_domain_field]
184
+ plan_obj = AppManager::Client.new
185
+ plans = plan_obj.get_plans(shop_domain)
186
+ plans = plans.select { |x| x['interval'] == 'EVERY_30_DAYS' && x['public'] == true }
187
+ plans.each do |plan|
188
+ next if (params && !params.nil? && params == "exclude_current_plan" && !shop_plan_id.nil? && plan["id"] == shop_plan_id)
189
+ if plan && (plan['features'] && plan['features'].any?) && (plan['features'].values && plan['features'].values.any?) && (plan['features'].values.collect { |c| c['slug'] } && plan['features'].values.collect { |c| c['slug'] }.any?)
190
+ plan_feature_slugs = plan['features'].values.collect { |c| c['slug'] }.sort
191
+ if (feature_slugs & plan_feature_slugs).any? && ((feature_slugs & plan_feature_slugs).sort == feature_slugs.sort)
192
+ plan_data.push(plan)
191
193
  end
192
- return plan_data
193
- else
194
- return []
194
+ end
195
195
  end
196
+ return plan_data
197
+ else
198
+ return []
199
+ end
196
200
  end
197
201
 
198
202
 
199
-
200
203
  def fetch_static_remaining_days
201
- @remaining_cache_key = "app-manager-cache/#{self.shopify_domain}-remaining_days"
202
- if fetch_cached_static_remaining_days(@remaining_cache_key).present?
203
- return fetch_cached_static_remaining_days(@remaining_cache_key)
204
- end
205
- remaining_days = self.get_remaining_days
206
- Rails.cache.write(@remaining_cache_key, remaining_days, expires_in: AppManager.configuration.expires_in)
207
- return remaining_days
204
+ @remaining_cache_key = "app-manager-cache/#{self.shopify_domain}-remaining_days"
205
+ if fetch_cached_static_remaining_days(@remaining_cache_key).present?
206
+ return fetch_cached_static_remaining_days(@remaining_cache_key)
208
207
  end
208
+ remaining_days = self.get_remaining_days
209
+ Rails.cache.write(@remaining_cache_key, remaining_days, expires_in: AppManager.configuration.expires_in)
210
+ return remaining_days
211
+ end
209
212
 
210
- def fetch_cached_static_remaining_days(cache_key)
211
- if Rails.cache.read(cache_key).present?
212
- return Rails.cache.read(cache_key)
213
- end
213
+ def fetch_cached_static_remaining_days(cache_key)
214
+ if Rails.cache.read(cache_key).present?
215
+ return Rails.cache.read(cache_key)
214
216
  end
215
-
217
+ end
216
218
 
217
219
 
218
220
  def fetch_static_get_charge
219
- @get_charge_key = "app-manager-cache/#{self.shopify_domain}-get_charge"
220
- if fetch_cached_static_get_charge(@get_charge_key).present?
221
- return fetch_cached_static_get_charge(@get_charge_key)
222
- end
223
- charge = self.get_charge
224
- Rails.cache.write(@get_charge_key, charge, expires_in: AppManager.configuration.expires_in)
225
- return charge
221
+ @get_charge_key = "app-manager-cache/#{self.shopify_domain}-get_charge"
222
+ if fetch_cached_static_get_charge(@get_charge_key).present?
223
+ return fetch_cached_static_get_charge(@get_charge_key)
224
+ end
225
+ charge = self.get_charge
226
+ Rails.cache.write(@get_charge_key, charge, expires_in: AppManager.configuration.expires_in)
227
+ return charge
226
228
  end
227
229
 
228
230
  def fetch_cached_static_get_charge(cache_key)
229
- if Rails.cache.read(cache_key).present?
230
- return Rails.cache.read(cache_key)
231
- end
231
+ if Rails.cache.read(cache_key).present?
232
+ return Rails.cache.read(cache_key)
233
+ end
232
234
  end
233
235
 
234
236
 
235
237
  private
236
-
237
- def casted_value(value,value_type)
238
- case value_type
239
- when "integer"
238
+
239
+ def casted_value(value, value_type)
240
+ case value_type
241
+ when "integer"
240
242
  value.to_i
241
- when "boolean"
242
- case value
243
- when true, 'true', 1, '1'
244
- return true
245
- when false, 'false', 0, '0'
246
- return false
247
- end
248
- when "string"
243
+ when "boolean"
244
+ case value
245
+ when true, 'true', 1, '1'
246
+ return true
247
+ when false, 'false', 0, '0'
248
+ return false
249
+ end
250
+ when "string"
249
251
  value.to_s
250
- else
252
+ else
251
253
  value
252
- end
254
+ end
253
255
  end
254
256
 
255
-
256
-
257
-
258
257
 
259
258
  end
260
- end
259
+ end
@@ -4,9 +4,8 @@ namespace :sync do
4
4
  begin
5
5
  @fs = AppManager::FailSafe.new
6
6
  @fs.sync_app_manager
7
- puts "app manager sync successfully"
8
- rescue Exception => e
9
- Rails.logger.info "APP MANAGER SYNC TAKS FAILED #{e.inspect}"
7
+ rescue Exception => e
8
+ Rollbar.error("APP MANAGER SYNC TAKS FAILED #{e.inspect}")
10
9
  end
11
10
  end
12
11
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppManager
4
- VERSION = "1.2.5"
4
+ VERSION = "1.3.0"
5
5
  end
data/lib/app_manager.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "httparty"
4
4
  require "rails"
5
- require 'sqlite3'
5
+ # require 'sqlite3'
6
6
  require "app_manager/version"
7
7
  require "app_manager/engine"
8
8
  require "app_manager/client"
@@ -29,8 +29,8 @@ module AppManager
29
29
  def self.clear_cache
30
30
  begin
31
31
  Rails.cache.delete_matched('app-manager-cache/*')
32
- rescue Exception => e
33
- Rails.logger.info "APP MANAGER >>>> #{e.inspect}"
32
+ rescue Exception => e
33
+ Rollbar.error("APP MANAGER Error in Clear Cache #{e}")
34
34
  end
35
35
  end
36
36
 
@@ -2,42 +2,51 @@ require "rails/generators/base"
2
2
  require "rails/generators/active_record"
3
3
 
4
4
  module AppManager
5
- module Generators
6
- class InstallGenerator < Rails::Generators::Base
7
- include Rails::Generators::Migration
8
- source_root File.expand_path('../templates', __FILE__)
9
-
10
- def mount_engine
11
- route("mount AppManager::Engine, at: '/'")
12
- end
13
-
14
- # def create_initializer_file
15
- # copy_file("plan_features.rb", "config/initializers/plan_features.rb")
16
- # end
17
-
18
- def create_app_manager_initializer
19
- template("app_manager.rb", "config/initializers/app_manager.rb")
20
- end
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ def mount_engine
11
+ route("mount AppManager::Engine, at: '/'")
12
+ end
13
+
14
+ def create_app_manager_initializer
15
+ template("app_manager.rb", "config/initializers/app_manager.rb")
16
+ end
17
+
18
+ def create_plan_trial_grandfathered_to_shops_migration
19
+ if self.class.migration_exists?("db/migrate", "add_plan_trial_grandfathered_to_shops")
20
+ say_status("skipped", "Migration add_plan_trial_grandfathered_to_shops.rb already exists")
21
+ else
22
+ migration_template("add_plan_trial_grandfathered_to_shops.erb", "db/migrate/add_plan_trial_grandfathered_to_shops.rb")
23
+ end
24
+ end
21
25
 
22
- def create_plan_trial_grandfathered_to_shops_migration
23
- migration_template("add_plan_trial_grandfathered_to_shops.erb", "db/migrate/add_plan_trial_grandfathered_to_shops.rb")
24
- end
26
+ def create_fail_safe
27
+ if self.class.migration_exists?("db/app_manager", "failsafe_tables")
28
+ say_status("skipped", "Migration add_fail_safe.rb already exists")
29
+ else
30
+ migration_template("failsafe_tables.erb", "db/app_manager/add_fail_safe.rb")
31
+ end
32
+ end
25
33
 
26
- private
27
34
 
28
- def rails_migration_version
29
- Rails.version.match(/\d\.\d/)[0]
30
- end
35
+ private
31
36
 
32
- class << self
33
- private :next_migration_number
37
+ def rails_migration_version
38
+ Rails.version.match(/\d\.\d/)[0]
39
+ end
34
40
 
35
- # for generating a timestamp when using `create_migration`
36
- def next_migration_number(dir)
37
- ActiveRecord::Generators::Base.next_migration_number(dir)
38
- end
39
- end
41
+ class << self
42
+ private :next_migration_number
40
43
 
44
+ # for generating a timestamp when using `create_migration`
45
+ def next_migration_number(dir)
46
+ ActiveRecord::Generators::Base.next_migration_number(dir)
41
47
  end
48
+ end
49
+
42
50
  end
43
- end
51
+ end
52
+ end