app_manager 1.6.3 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c143606bbac6f53820f8522a8a735c33a1d241bc6c2bc919d75bb8319d44aebf
4
- data.tar.gz: 770f14a16a4c912389bfd71106a517af68e724645cc68bd6c9153d61b0d34dee
3
+ metadata.gz: 1093f4ae3ee06a00f81bf11ad98bb1669f6b9f931bed69a430525733058143a0
4
+ data.tar.gz: 9a3a425bdf82d12982f33ace1e86a1e5b47bbc7b3430ccd96b0469967cbf2f65
5
5
  SHA512:
6
- metadata.gz: 40a9cdb0477e5c3b3aa51cc8d5f03be15deab919199f101b237cb0063db42e2d160e72a52aa111b56f5736c1fcadc4a16cd557a45bed0c2fbf914e285eb1763d
7
- data.tar.gz: efdc457510fb1372aa92915d8109f0fd0963dc49d7b18564a725527b932efa3e295d47249b2d75340d00ee517cd47cfbfa30c32b1a7177c5de12130d2396b10e
6
+ metadata.gz: 9306209e778f2593afc88cdaf1f468f8c0ccefddd197e3ecfcb516301581577131975ed73dde14decae361454d32955f25c80220edab9cc755955f986d37a747
7
+ data.tar.gz: b0f6d9c366e807ebaa5d5fd5de056ecd3f7e93addfbdc944cda14ec915dc86a5e20d4b248426dfe04bc7c5962887d858fd01eed6de2bc4ae7c5976540e9c8c6a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- app_manager (1.6.3)
4
+ app_manager (2.0.0)
5
5
  activerecord-import (~> 1.4)
6
6
  httparty
7
7
  kaminari (>= 0.16.3)
@@ -10,93 +10,110 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- actioncable (7.0.5)
14
- actionpack (= 7.0.5)
15
- activesupport (= 7.0.5)
13
+ actioncable (7.1.3.2)
14
+ actionpack (= 7.1.3.2)
15
+ activesupport (= 7.1.3.2)
16
16
  nio4r (~> 2.0)
17
17
  websocket-driver (>= 0.6.1)
18
- actionmailbox (7.0.5)
19
- actionpack (= 7.0.5)
20
- activejob (= 7.0.5)
21
- activerecord (= 7.0.5)
22
- activestorage (= 7.0.5)
23
- activesupport (= 7.0.5)
18
+ zeitwerk (~> 2.6)
19
+ actionmailbox (7.1.3.2)
20
+ actionpack (= 7.1.3.2)
21
+ activejob (= 7.1.3.2)
22
+ activerecord (= 7.1.3.2)
23
+ activestorage (= 7.1.3.2)
24
+ activesupport (= 7.1.3.2)
24
25
  mail (>= 2.7.1)
25
26
  net-imap
26
27
  net-pop
27
28
  net-smtp
28
- actionmailer (7.0.5)
29
- actionpack (= 7.0.5)
30
- actionview (= 7.0.5)
31
- activejob (= 7.0.5)
32
- activesupport (= 7.0.5)
29
+ actionmailer (7.1.3.2)
30
+ actionpack (= 7.1.3.2)
31
+ actionview (= 7.1.3.2)
32
+ activejob (= 7.1.3.2)
33
+ activesupport (= 7.1.3.2)
33
34
  mail (~> 2.5, >= 2.5.4)
34
35
  net-imap
35
36
  net-pop
36
37
  net-smtp
37
- rails-dom-testing (~> 2.0)
38
- actionpack (7.0.5)
39
- actionview (= 7.0.5)
40
- activesupport (= 7.0.5)
41
- rack (~> 2.0, >= 2.2.4)
38
+ rails-dom-testing (~> 2.2)
39
+ actionpack (7.1.3.2)
40
+ actionview (= 7.1.3.2)
41
+ activesupport (= 7.1.3.2)
42
+ nokogiri (>= 1.8.5)
43
+ racc
44
+ rack (>= 2.2.4)
45
+ rack-session (>= 1.0.1)
42
46
  rack-test (>= 0.6.3)
43
- rails-dom-testing (~> 2.0)
44
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
45
- actiontext (7.0.5)
46
- actionpack (= 7.0.5)
47
- activerecord (= 7.0.5)
48
- activestorage (= 7.0.5)
49
- activesupport (= 7.0.5)
47
+ rails-dom-testing (~> 2.2)
48
+ rails-html-sanitizer (~> 1.6)
49
+ actiontext (7.1.3.2)
50
+ actionpack (= 7.1.3.2)
51
+ activerecord (= 7.1.3.2)
52
+ activestorage (= 7.1.3.2)
53
+ activesupport (= 7.1.3.2)
50
54
  globalid (>= 0.6.0)
51
55
  nokogiri (>= 1.8.5)
52
- actionview (7.0.5)
53
- activesupport (= 7.0.5)
56
+ actionview (7.1.3.2)
57
+ activesupport (= 7.1.3.2)
54
58
  builder (~> 3.1)
55
- erubi (~> 1.4)
56
- rails-dom-testing (~> 2.0)
57
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
58
- activejob (7.0.5)
59
- activesupport (= 7.0.5)
59
+ erubi (~> 1.11)
60
+ rails-dom-testing (~> 2.2)
61
+ rails-html-sanitizer (~> 1.6)
62
+ activejob (7.1.3.2)
63
+ activesupport (= 7.1.3.2)
60
64
  globalid (>= 0.3.6)
61
- activemodel (7.0.5)
62
- activesupport (= 7.0.5)
63
- activerecord (7.0.5)
64
- activemodel (= 7.0.5)
65
- activesupport (= 7.0.5)
66
- activerecord-import (1.4.1)
65
+ activemodel (7.1.3.2)
66
+ activesupport (= 7.1.3.2)
67
+ activerecord (7.1.3.2)
68
+ activemodel (= 7.1.3.2)
69
+ activesupport (= 7.1.3.2)
70
+ timeout (>= 0.4.0)
71
+ activerecord-import (1.5.1)
67
72
  activerecord (>= 4.2)
68
- activestorage (7.0.5)
69
- actionpack (= 7.0.5)
70
- activejob (= 7.0.5)
71
- activerecord (= 7.0.5)
72
- activesupport (= 7.0.5)
73
+ activestorage (7.1.3.2)
74
+ actionpack (= 7.1.3.2)
75
+ activejob (= 7.1.3.2)
76
+ activerecord (= 7.1.3.2)
77
+ activesupport (= 7.1.3.2)
73
78
  marcel (~> 1.0)
74
- mini_mime (>= 1.1.0)
75
- activesupport (7.0.5)
79
+ activesupport (7.1.3.2)
80
+ base64
81
+ bigdecimal
76
82
  concurrent-ruby (~> 1.0, >= 1.0.2)
83
+ connection_pool (>= 2.2.5)
84
+ drb
77
85
  i18n (>= 1.6, < 2)
78
86
  minitest (>= 5.1)
87
+ mutex_m
79
88
  tzinfo (~> 2.0)
80
89
  addressable (2.8.0)
81
90
  public_suffix (>= 2.0.2, < 5.0)
91
+ base64 (0.2.0)
92
+ bigdecimal (3.1.6)
82
93
  builder (3.2.4)
83
94
  coderay (1.1.3)
84
- concurrent-ruby (1.2.2)
95
+ concurrent-ruby (1.2.3)
96
+ connection_pool (2.4.1)
85
97
  crack (0.4.5)
86
98
  rexml
87
99
  crass (1.0.6)
88
- date (3.3.3)
100
+ date (3.3.4)
89
101
  diff-lcs (1.5.0)
90
102
  dotenv (2.1.2)
103
+ drb (2.2.1)
91
104
  erubi (1.12.0)
92
- globalid (1.1.0)
93
- activesupport (>= 5.0)
105
+ globalid (1.2.1)
106
+ activesupport (>= 6.1)
94
107
  hashdiff (1.0.1)
95
108
  httparty (0.21.0)
96
109
  mini_mime (>= 1.0.0)
97
110
  multi_xml (>= 0.5.2)
98
- i18n (1.14.1)
111
+ i18n (1.14.4)
99
112
  concurrent-ruby (~> 1.0)
113
+ io-console (0.7.2)
114
+ irb (1.12.0)
115
+ rdoc
116
+ reline (>= 0.4.2)
100
117
  kaminari (1.2.2)
101
118
  activesupport (>= 4.1.0)
102
119
  kaminari-actionview (= 1.2.2)
@@ -109,7 +126,7 @@ GEM
109
126
  activerecord
110
127
  kaminari-core (= 1.2.2)
111
128
  kaminari-core (1.2.2)
112
- loofah (2.21.3)
129
+ loofah (2.22.0)
113
130
  crass (~> 1.0.2)
114
131
  nokogiri (>= 1.12.0)
115
132
  mail (2.8.1)
@@ -117,61 +134,75 @@ GEM
117
134
  net-imap
118
135
  net-pop
119
136
  net-smtp
120
- marcel (1.0.2)
137
+ marcel (1.0.4)
121
138
  method_source (1.0.0)
122
- mini_mime (1.1.2)
123
- mini_portile2 (2.8.2)
124
- minitest (5.18.0)
139
+ mini_mime (1.1.5)
140
+ mini_portile2 (2.8.5)
141
+ minitest (5.22.2)
125
142
  multi_xml (0.6.0)
126
- net-imap (0.3.4)
143
+ mutex_m (0.2.0)
144
+ net-imap (0.3.7)
127
145
  date
128
146
  net-protocol
129
147
  net-pop (0.1.2)
130
148
  net-protocol
131
- net-protocol (0.2.1)
149
+ net-protocol (0.2.2)
132
150
  timeout
133
- net-smtp (0.3.3)
151
+ net-smtp (0.4.0.1)
134
152
  net-protocol
135
- nio4r (2.5.9)
136
- nokogiri (1.15.2)
153
+ nio4r (2.7.0)
154
+ nokogiri (1.15.5)
137
155
  mini_portile2 (~> 2.8.2)
138
156
  racc (~> 1.4)
139
157
  pry (0.14.1)
140
158
  coderay (~> 1.1)
141
159
  method_source (~> 1.0)
160
+ psych (5.1.2)
161
+ stringio
142
162
  public_suffix (4.0.6)
143
- racc (1.7.0)
144
- rack (2.2.7)
163
+ racc (1.7.3)
164
+ rack (3.0.9.1)
165
+ rack-session (2.0.0)
166
+ rack (>= 3.0.0)
145
167
  rack-test (2.1.0)
146
168
  rack (>= 1.3)
147
- rails (7.0.5)
148
- actioncable (= 7.0.5)
149
- actionmailbox (= 7.0.5)
150
- actionmailer (= 7.0.5)
151
- actionpack (= 7.0.5)
152
- actiontext (= 7.0.5)
153
- actionview (= 7.0.5)
154
- activejob (= 7.0.5)
155
- activemodel (= 7.0.5)
156
- activerecord (= 7.0.5)
157
- activestorage (= 7.0.5)
158
- activesupport (= 7.0.5)
169
+ rackup (2.1.0)
170
+ rack (>= 3)
171
+ webrick (~> 1.8)
172
+ rails (7.1.3.2)
173
+ actioncable (= 7.1.3.2)
174
+ actionmailbox (= 7.1.3.2)
175
+ actionmailer (= 7.1.3.2)
176
+ actionpack (= 7.1.3.2)
177
+ actiontext (= 7.1.3.2)
178
+ actionview (= 7.1.3.2)
179
+ activejob (= 7.1.3.2)
180
+ activemodel (= 7.1.3.2)
181
+ activerecord (= 7.1.3.2)
182
+ activestorage (= 7.1.3.2)
183
+ activesupport (= 7.1.3.2)
159
184
  bundler (>= 1.15.0)
160
- railties (= 7.0.5)
161
- rails-dom-testing (2.0.3)
162
- activesupport (>= 4.2.0)
185
+ railties (= 7.1.3.2)
186
+ rails-dom-testing (2.2.0)
187
+ activesupport (>= 5.0.0)
188
+ minitest
163
189
  nokogiri (>= 1.6)
164
190
  rails-html-sanitizer (1.6.0)
165
191
  loofah (~> 2.21)
166
192
  nokogiri (~> 1.14)
167
- railties (7.0.5)
168
- actionpack (= 7.0.5)
169
- activesupport (= 7.0.5)
170
- method_source
193
+ railties (7.1.3.2)
194
+ actionpack (= 7.1.3.2)
195
+ activesupport (= 7.1.3.2)
196
+ irb
197
+ rackup (>= 1.0.0)
171
198
  rake (>= 12.2)
172
- thor (~> 1.0)
173
- zeitwerk (~> 2.5)
199
+ thor (~> 1.0, >= 1.2.2)
200
+ zeitwerk (~> 2.6)
174
201
  rake (13.0.6)
202
+ rdoc (6.6.2)
203
+ psych (>= 4.0.0)
204
+ reline (0.4.3)
205
+ io-console (~> 0.5)
175
206
  rexml (3.2.5)
176
207
  rspec (3.11.0)
177
208
  rspec-core (~> 3.11.0)
@@ -188,18 +219,20 @@ GEM
188
219
  diff-lcs (>= 1.2.0, < 2.0)
189
220
  rspec-support (~> 3.11.0)
190
221
  rspec-support (3.11.0)
191
- thor (1.2.2)
192
- timeout (0.3.2)
222
+ stringio (3.1.0)
223
+ thor (1.3.1)
224
+ timeout (0.4.1)
193
225
  tzinfo (2.0.6)
194
226
  concurrent-ruby (~> 1.0)
195
227
  webmock (3.14.0)
196
228
  addressable (>= 2.8.0)
197
229
  crack (>= 0.3.2)
198
230
  hashdiff (>= 0.4.0, < 2.0.0)
199
- websocket-driver (0.7.5)
231
+ webrick (1.8.1)
232
+ websocket-driver (0.7.6)
200
233
  websocket-extensions (>= 0.1.0)
201
234
  websocket-extensions (0.1.5)
202
- zeitwerk (2.6.8)
235
+ zeitwerk (2.6.13)
203
236
 
204
237
  PLATFORMS
205
238
  ruby
data/README.md CHANGED
@@ -209,8 +209,43 @@ and then you can use follwing methods with your shop objects.
209
209
  @shop.active_shopfiy_charge_full #It will give shopify recurring charge graphql object with discounted price details
210
210
  ```
211
211
 
212
-
213
212
  <a name="step4"></a>
213
+ ### Discount Link Integration
214
+
215
+ * Update app manager vue package in Rails+Vue apps & for for non-vue apps, update css or js from npm package, minimum version should be 2.4.4
216
+
217
+ * Update app manager gem in your project's Gemfile
218
+
219
+ ```ruby
220
+ gem 'app_manager', '2.0.0'
221
+ ```
222
+ * In Rails project, in application.rb, add following line after require "rails/all" line
223
+
224
+ ```ruby
225
+ require 'app_manager/set_cookie'
226
+ ```
227
+
228
+ * In route.rb file, add following route with constraints
229
+ ```ruby
230
+ condition = ->(request) { request.path_info.include?('/discount/') }
231
+ constraints(condition) do
232
+ get '/discount/*any', to: AppManager::SetCookie.new(Rails.application, condition)
233
+ end
234
+ ```
235
+ * If updating gem from 1.6.1, then run these commands on rails root.
236
+
237
+ Note: In this command, Please do not overwrite app_manager.rb file so press n
238
+ ```ruby
239
+ rails g app_manager:install
240
+ ```
241
+ This will add a new migration file in your db/app_manager directory
242
+
243
+ ```ruby
244
+ rails db:migrate
245
+ ```
246
+
247
+
248
+ <a name="step5"></a>
214
249
  ### Extras
215
250
 
216
251
  * To view the app_manager ruby gem is working in your rails app you can use rails console and initialize app_manager instance like with App Manager Portal access:
@@ -58,17 +58,20 @@ module AppManager
58
58
  end
59
59
  end
60
60
  request_data = {'shop' => @shop.shopify_domain, 'timestamp' => Time.now.to_i, 'plan' => params[:plan_id]}
61
+ request_data.merge!('host' => params['host']) if params['host'].present?
62
+
61
63
  return_url = "#{app_url}#{plan_callback_path}?#{Rack::Utils.build_query(request_data)}"
64
+ discount_cookie = AppManager.resolve_from_cookies(self.request)
62
65
  gq_obj = AppManager::GraphqlHelper.new(@shop.shopify_domain, @shop.shopify_token)
63
- data = gq_obj.recurring_charge_api_call(plan_data, return_url, @shop)
64
- if !data["errors"].present? && (data["data"].present? && data["data"]["appSubscriptionCreate"].present? && (!data["data"]["appSubscriptionCreate"]["userErrors"].any? && data["data"]["appSubscriptionCreate"]["confirmationUrl"]))
66
+ data = gq_obj.recurring_charge_api_call(plan_data, return_url, @shop,discount_cookie)
67
+ if data.present? && !data["errors"].present? && (data["data"].present? && data["data"]["appSubscriptionCreate"].present? && (!data["data"]["appSubscriptionCreate"]["userErrors"].any? && data["data"]["appSubscriptionCreate"]["confirmationUrl"]))
65
68
  redirect_charge = data["data"]["appSubscriptionCreate"]["confirmationUrl"]
66
69
  render json: {'redirect_url' => redirect_charge}
67
70
  else
68
71
  raise Error, "#{data.inspect}"
69
72
  end
70
73
  else
71
- raise Error, "#{data.inspect}"
74
+ raise Error, "Plan not found"
72
75
  end
73
76
  else
74
77
  raise ModelNotFound, "Shop not found"
@@ -85,6 +88,8 @@ module AppManager
85
88
  shopify_token = @field_names['shopify_token']
86
89
  shopify_domain = @field_names['name']
87
90
  grandfathered_field = @field_names['grandfathered']
91
+ discounted_plans = JSON.parse(params[:discounted_plans]) rescue []
92
+ discounted_plans = discounted_plans.map!(&:to_s) if discounted_plans.any?
88
93
  if !@shop.nil?
89
94
  old_plan_id = @shop[@plan_field]
90
95
  old_plan_data = nil
@@ -131,8 +136,23 @@ module AppManager
131
136
  rescue Exception => e
132
137
  Rollbar.error("Error in APP MANAGER Charge Created Callback >>>> #{e.inspect}")
133
138
  end
139
+
140
+ begin
141
+ plan_obj = AppManager::Client.new
142
+ discounted_plans_present = discounted_plans.present? && discounted_plans.any?
143
+ if params[:promo_discount].present? && discounted_plans_present && discounted_plans.include?(params[:plan])
144
+ plan_obj.discount_used(@shop[shopify_domain], params[:promo_discount])
145
+ elsif params[:promo_discount].present? && discounted_plans.blank?
146
+ plan_obj.discount_used(@shop[shopify_domain], params[:promo_discount])
147
+ end
148
+ rescue
149
+ Rollbar.error("Error in APP MANAGER Discount used API call >>>> #{e.inspect}")
150
+ end
134
151
  end
135
152
  end
153
+
154
+
155
+
136
156
  embed_host = Base64.encode64(params[:shop] + "/admin")
137
157
 
138
158
  if !old_plan_id.nil?
@@ -65,8 +65,19 @@ module AppManager
65
65
  end
66
66
  end
67
67
 
68
+ promotional_discount = []
69
+ discount_cookie = AppManager.resolve_from_cookies(self.request)
70
+ if discount_cookie && @shop
71
+ created_at = @shop[AppManager.configuration.field_names['created_at']]
72
+ reinstall = AppManager.check_if_reinstall(created_at)
73
+ plan_obj = AppManager::Client.new
74
+ promotional_discount = plan_obj.get_promotional_discount(params[:shop_domain], discount_cookie['codeType'], discount_cookie['code'], reinstall)
75
+ promotional_discount = [] if promotional_discount.class.to_s == "Hash" && promotional_discount.has_key?('status') && promotional_discount['status'] == 404
76
+ end
77
+
68
78
  response = {
69
79
  'plans' => plans,
80
+ 'promotional_discount' => promotional_discount,
70
81
  'shopify_plan' => shopify_plan,
71
82
  'plan' => plan,
72
83
  'default_plan_id' => default_plan_id,
@@ -90,12 +101,12 @@ module AppManager
90
101
  @shopify_email = AppManager.configuration.field_names['shopify_email']
91
102
  @shopify_plan_name_field = AppManager.configuration.field_names['shopify_plan']
92
103
  if params[:search]
93
- data = model.where("#{@shopify_domain} LIKE :search OR #{@shopify_email} LIKE :search", search: "%#{search}%")
104
+ data = model.where("#{@shopify_domain} LIKE :search OR #{@shopify_email} LIKE :search", search: "%#{search}%").order(sort + " " + order)
94
105
  data = data.where(@plan_field => plans) if !plans.nil?
95
106
  data = data.where(@shopify_plan_name_field => shopify_plans) if !shopify_plans.nil?
96
107
  data = data.page(params[:page]).per(items_per_page)
97
108
  else
98
- data = model
109
+ data = model.order(sort + " " + order)
99
110
  data = data.where(@plan_field => plans) if !plans.nil?
100
111
  data = data.where(@shopify_plan_name_field => shopify_plans) if !shopify_plans.nil?
101
112
  data = data.page(params[:page]).per(items_per_page)
@@ -0,0 +1,5 @@
1
+ module AppManager
2
+ class Discount < AppManagerRecord
3
+ self.table_name = "discounts"
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module AppManager
2
+ class DiscountLinkPlan < AppManagerRecord
3
+ self.table_name = "discount_link_plans"
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module AppManager
2
+ class DiscountShop < AppManagerRecord
3
+ self.table_name = "discount_shops"
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module AppManager
2
+ class DiscountUsageLog < AppManagerRecord
3
+ self.table_name = "discounts_usage_log"
4
+ end
5
+ end
@@ -28,8 +28,19 @@ module AppManager
28
28
  response = response_from_cache_for_api(http_method, path, options)
29
29
  failsafe_or_caching_done = true
30
30
  else
31
- time_out = Rails.env.development? ? 120 : 30
32
- response = self.class.send(http_method, path, { body: options, timeout: time_out })
31
+ time_out = Rails.env.development? ? 120 : 120
32
+ begin
33
+ response = self.class.send(http_method, path, { body: options, timeout: time_out })
34
+ rescue Net::ReadTimeout => error
35
+ # Handle timeout error here
36
+ Rails.logger.info "Net::ReadTimeout: Request timed out. Please try again."
37
+ response = response_from_failsafe(path, options)
38
+ rescue StandardError => e
39
+ # Handle other errors
40
+ Rails.logger.info "Error: #{e.message}"
41
+ response = response_from_failsafe(path, options)
42
+ end
43
+
33
44
  end
34
45
  if path.include? "/get-status"
35
46
  data = response
@@ -42,7 +53,10 @@ module AppManager
42
53
  data = parse_data(response.parsed_response)
43
54
  # data = response_from_failsafe(path,options) #uncomment to test failsafe
44
55
  return data
45
- else
56
+ elsif ((response.class == Hash) && response.has_key?("message"))
57
+ data = parse_data(response)
58
+ return data
59
+ else
46
60
  if failsafe_or_caching_done == true
47
61
  data = response
48
62
  return data
@@ -60,7 +74,7 @@ module AppManager
60
74
  return fetch_static_cached_response(cache_key)
61
75
  end
62
76
  begin
63
- response = self.class.send(http_method, path, { body: options, timeout: 15 })
77
+ response = self.class.send(http_method, path, { body: options, timeout: 1 })
64
78
  if response.class.to_s == "HTTParty::Response" && (response.code.to_s.start_with?('2') or response.code.to_s.start_with?('4')) && (response.code.to_s != '429')
65
79
  Rails.cache.write(cache_key, response, expires_in: AppManager.configuration.expires_in)
66
80
  else
@@ -68,6 +82,8 @@ module AppManager
68
82
  end
69
83
  rescue Net::ReadTimeout => error
70
84
  response = response_from_failsafe(path,options)
85
+ rescue StandardError => error
86
+ response = response_from_failsafe(path, options)
71
87
  rescue Exception => e
72
88
  response = response_from_failsafe(path,options)
73
89
  end
@@ -111,6 +127,10 @@ module AppManager
111
127
  return @fs.get_local_charge(params,options)
112
128
  when 'has-plan'
113
129
  return @fs.get_local_has_plan(params, options)
130
+ when 'discount'
131
+ return @fs.get_local_discount(params, options)
132
+ when 'use-discount'
133
+ return @fs.store_discount_used(params,options)
114
134
  else
115
135
  return nil
116
136
  end
@@ -26,6 +26,7 @@ module AppManager
26
26
  post("/sync-charge", options)
27
27
  end
28
28
 
29
+
29
30
  def get_remaining_days(shop_domain, trial_activated_at = nil, plan_id = nil)
30
31
  get("/get-remaining-days?shop_domain=#{shop_domain}&trial_activated_at=#{trial_activated_at}&plan_id=#{plan_id}")
31
32
  end
@@ -42,6 +43,17 @@ module AppManager
42
43
  get("/has-plan?shop_domain=#{shop_domain}&plan_id=#{plan_id}&trial_activated_at=#{trial_activated_at}&grandfathered=#{grandfathered}")
43
44
  end
44
45
 
46
+ def get_promotional_discount(shop_domain = nil, code_type, code, reinstall)
47
+ get("/discount?shop_domain=#{shop_domain}&reinstall=#{reinstall}&code_type=#{code_type}&code=#{code}")
48
+ end
49
+
50
+ def discount_used(shop_domain, discount_id)
51
+ post('/use-discount', {shop_domain: shop_domain, discount_id: discount_id.to_i})
52
+ end
53
+
54
+ def sync_discount_usage_log(options = {})
55
+ post("/use-discount-sync", options)
56
+ end
45
57
 
46
58
  end
47
59
  end
@@ -52,7 +52,7 @@ module AppManager
52
52
  begin
53
53
  save_api_extend_trials(params["extend_trials"])
54
54
  rescue Exception => e
55
- Rollbar.error("[Extens Trials] APP MANAGER >>>> #{e.inspect}")
55
+ Rollbar.error("[Extend Trials] APP MANAGER >>>> #{e.inspect}")
56
56
  end
57
57
 
58
58
  begin
@@ -60,6 +60,31 @@ module AppManager
60
60
  rescue Exception => e
61
61
  Rollbar.error("[Plan User] APP MANAGER >>>> #{e.inspect}")
62
62
  end
63
+
64
+ begin
65
+ save_api_promotional_discounts(params["promotional_discounts"])
66
+ rescue Exception => e
67
+ Rollbar.error("[Promotional discounts] APP MANAGER >>>> #{e.inspect}")
68
+ end
69
+
70
+ begin
71
+ save_api_promotional_discounts_shops(params["promotional_discounts_shops"])
72
+ rescue Exception => e
73
+ Rollbar.error("[Promotional discounts shops] APP MANAGER >>>> #{e.inspect}")
74
+ end
75
+
76
+ begin
77
+ save_api_promotional_discounts_link_plans(params["promotional_discounts_plans"])
78
+ rescue Exception => e
79
+ Rollbar.error("[Promotional discounts plans] APP MANAGER >>>> #{e.inspect}")
80
+ end
81
+
82
+ begin
83
+ save_api_promotional_discounts_usage_log(params["promotional_discounts_usage_log"])
84
+ rescue Exception => e
85
+ Rollbar.error("[Promotional discounts usage log] APP MANAGER >>>> #{e.inspect}")
86
+ end
87
+
63
88
  end
64
89
 
65
90
  def save_api_plans(plans)
@@ -185,7 +210,113 @@ module AppManager
185
210
  extend_plan_users << AppManager::PlanUser.new(plan_user_id: plan_user['id'],shop_domain: plan_user['shop_domain'], plan_id: plan_user['plan_id'], created_by: plan_user['created_by'], created_at: plan_user['created_at'], updated_at: plan_user['updated_at'])
186
211
  # extend_plan_users << AppManager::PlanUser.new(id: plan_user['id'], shop_domain: plan_user['shop_domain'], plan_id: plan_user['plan_id'], created_by: plan_user['created_by'], created_at: plan_user['created_at'], updated_at: plan_user['updated_at'])
187
212
  end
188
- AppManager::ExtendTrial.bulk_import extend_plan_users
213
+ AppManager::PlanUser.bulk_import extend_plan_users
214
+ end
215
+ end
216
+
217
+ def save_api_promotional_discounts(promotional_discounts)
218
+ begin
219
+ AppManager::Discount.connection.truncate(AppManager::Discount.table_name)
220
+ rescue
221
+ AppManager::Discount.delete_all
222
+ end
223
+ if promotional_discounts.any?
224
+ promotional_discounts_data = []
225
+ promotional_discounts.each do |promotional_discount|
226
+
227
+ Rails.logger.info " "
228
+ Rails.logger.info "=== promotional_discount===========#{promotional_discount.inspect}"
229
+ Rails.logger.info " "
230
+
231
+ promotional_discounts_data << AppManager::Discount.new(
232
+ discount_id: promotional_discount['id'],
233
+ name: promotional_discount['name'],
234
+ code: promotional_discount['code'],
235
+ discount_type: promotional_discount['type'] || 'amount',
236
+ value: promotional_discount['value'] || 0,
237
+ duration_intervals: promotional_discount['duration_intervals'],
238
+ max_usage: promotional_discount['max_usage'],
239
+ enabled: promotional_discount['enabled'],
240
+ valid_from: promotional_discount['valid_from'],
241
+ valid_to: promotional_discount['valid_to'],
242
+ priority: promotional_discount['priority'] || 0,
243
+ multiple_uses: promotional_discount['multiple_uses'],
244
+ multiple_apps: promotional_discount['multiple_apps'],
245
+ app_id: promotional_discount['app_id'] || 0,
246
+ created_at: promotional_discount['created_at'],
247
+ updated_at: promotional_discount['updated_at'],
248
+ deleted_at: promotional_discount['deleted_at']
249
+ )
250
+ end
251
+
252
+ Rails.logger.info " "
253
+ Rails.logger.info "=== promotional_discounts_data===========#{promotional_discounts_data.inspect}"
254
+ Rails.logger.info " "
255
+ AppManager::Discount.bulk_import promotional_discounts_data
256
+ end
257
+ end
258
+
259
+ def save_api_promotional_discounts_shops(promotional_discounts_shops)
260
+
261
+ begin
262
+ AppManager::DiscountShop.connection.truncate(AppManager::DiscountShop.table_name)
263
+ rescue
264
+ AppManager::DiscountShop.delete_all
265
+ end
266
+
267
+ if promotional_discounts_shops.any?
268
+ promotional_discounts_shop_data = []
269
+ promotional_discounts_shops.each do |promotional_discounts_shop|
270
+ promotional_discounts_shop_data << AppManager::DiscountShop.new(
271
+ discount_id: promotional_discounts_shop['discount_id'],
272
+ domain: promotional_discounts_shop['domain']
273
+ )
274
+ end
275
+ AppManager::DiscountShop.bulk_import promotional_discounts_shop_data
276
+ end
277
+ end
278
+
279
+ def save_api_promotional_discounts_link_plans(promotional_discounts_plans)
280
+
281
+ begin
282
+ AppManager::DiscountLinkPlan.connection.truncate(AppManager::DiscountLinkPlan.table_name)
283
+ rescue
284
+ AppManager::DiscountLinkPlan.delete_all
285
+ end
286
+
287
+ if promotional_discounts_plans.any?
288
+ discount_link_plans_data = []
289
+ promotional_discounts_plans.each do |link_plan|
290
+ discount_link_plans_data << AppManager::DiscountLinkPlan.new(
291
+ discount_id: link_plan['discount_id'],
292
+ plan_id: link_plan['plan_id']
293
+ )
294
+ end
295
+ AppManager::DiscountLinkPlan.bulk_import discount_link_plans_data
296
+ end
297
+ end
298
+
299
+ def save_api_promotional_discounts_usage_log(promotional_discounts_usage_log)
300
+ begin
301
+ AppManager::DiscountUsageLog.connection.truncate(AppManager::DiscountUsageLog.table_name)
302
+ rescue
303
+ AppManager::DiscountUsageLog.delete_all
304
+ end
305
+
306
+ if promotional_discounts_usage_log.any?
307
+ promotional_discounts_usage_log_data = []
308
+ promotional_discounts_usage_log.each do |log|
309
+ promotional_discounts_usage_log_data << AppManager::DiscountUsageLog.new(
310
+ discount_id: log['discount_id'],
311
+ app_id: log['app_id'],
312
+ domain: log['domain'],
313
+ sync: log['sync'],
314
+ process_type: log['process_type'],
315
+ created_at: log['created_at'],
316
+ updated_at: log['updated_at']
317
+ )
318
+ end
319
+ AppManager::DiscountUsageLog.bulk_import promotional_discounts_usage_log_data
189
320
  end
190
321
  end
191
322
 
@@ -262,6 +393,9 @@ module AppManager
262
393
  value = eval(value)
263
394
  value = value.each { |e| e.delete("id") }.each { |e| e.delete("created_at") }.each { |e| e.delete("updated_at") }
264
395
  new_plan[key] = value
396
+ elsif ['plan_id'].include?(key)
397
+ # puts value.inspect
398
+ new_plan["id"] = value if value rescue {}
265
399
  else
266
400
  new_plan[key] = value unless key.class == Integer
267
401
  end
@@ -350,6 +484,8 @@ module AppManager
350
484
  new_plan[key] = (value == 0 || value == false ? false : true)
351
485
  elsif ['test'].include?(key)
352
486
  new_plan[key] = (value == 0 || value == false ? nil : true)
487
+ elsif ['plan_id'].include?(key)
488
+ new_plan["id"] = value if value rescue nil
353
489
  else
354
490
  new_plan[key] = value unless key.class == Integer
355
491
  end
@@ -476,6 +612,68 @@ module AppManager
476
612
 
477
613
  end
478
614
 
615
+ def get_local_discount(params, options)
616
+ code = [params['code']].pack('H*')
617
+ code_type = params['code_type']
618
+ reinstall = params['reinstall']
619
+ shop_domain = params['shop_domain']
620
+ now = Time.now
621
+
622
+ discount_data = AppManager::Discount.where(enabled: true)
623
+ .where('valid_from <= ?', now)
624
+ .where('valid_to >= ?', now)
625
+ .where(code: code)
626
+ .first
627
+ return [] if discount_data.nil?
628
+
629
+ discount_shop = AppManager::DiscountShop.where(discount_id: discount_data.discount_id).count
630
+
631
+ discount_plan = AppManager::DiscountLinkPlan.where(discount_id: discount_data.discount_id).pluck('plan_id')
632
+
633
+ discount_usage = AppManager::DiscountUsageLog.where(discount_id: discount_data.discount_id).count
634
+
635
+ discount_usage_by_domain = AppManager::DiscountUsageLog.where(discount_id: discount_data.discount_id)
636
+ .where(domain: shop_domain)
637
+ .count
638
+ if discount_shop > 0
639
+ discount_shop_specific = AppManager::DiscountShop.where(discount_id: discount_data.discount_id)
640
+ .where(domain: shop_domain)
641
+ .first
642
+ return [] if discount_shop_specific.nil?
643
+ end
644
+
645
+ if discount_data.max_usage.present? && discount_data.max_usage != 0
646
+ return [] if discount_usage >= discount_data.max_usage
647
+ end
648
+
649
+ if discount_data.multiple_uses == false && discount_usage_by_domain >= 1
650
+ return []
651
+ end
652
+
653
+ if discount_data.multiple_apps == false
654
+ discount_usage_by_app = AppManager::DiscountUsageLog
655
+ .where(discount_id: discount_data.discount_id, domain: shop_domain)
656
+ .where.not(app_id: discount_data.app_id)
657
+ .first
658
+ return [] if discount_usage_by_app.present?
659
+ end
660
+
661
+
662
+ discount_data = discount_data.attributes.symbolize_keys
663
+ discount_data[:plan_relation] = discount_plan
664
+ final_mapped_data = {
665
+ "id" => discount_data[:discount_id],
666
+ "name" => discount_data[:name],
667
+ "type" => discount_data[:discount_type],
668
+ "value" => discount_data[:value].to_f,
669
+ "duration_intervals" => discount_data[:duration_intervals],
670
+ "plan_relation" => discount_data[:plan_relation]
671
+ } rescue {}
672
+
673
+ return JSON.parse(final_mapped_data.to_json)
674
+
675
+ end
676
+
479
677
  def store_local_charge(params, options)
480
678
  message = {"message" => 'fail'}
481
679
  if options
@@ -486,7 +684,7 @@ module AppManager
486
684
  test_value = charge["test"]
487
685
  plan_id = charge["plan_id"].to_i
488
686
  begin
489
- AppManager::Charge.create(charge_id: charge["charge_id"], test: test_value, status: charge["status"], name: charge["name"], type: charge["type"], price: charge["price"], interval: charge["interval"], trial_days: charge["trial_days"], billing_on: charge["billing_on"], activated_on: charge["activated_on"], trial_ends_on: charge["trial_ends_on"], cancelled_on: charge["cancelled_on"], expires_on: charge["expires_on"], plan_id: plan_id, description: charge["description"], shop_domain: charge["shop_domain"], created_at: charge["created_at"], updated_at: charge["updated_at"], sync: 0)
687
+ AppManager::Charge.create(charge_id: charge["charge_id"], test: test_value, status: charge["status"], name: charge["name"], type: charge["type"], price: charge["price"], interval: charge["interval"], trial_days: charge["trial_days"], billing_on: charge["billing_on"], activated_on: charge["activated_on"], trial_ends_on: charge["trial_ends_on"], cancelled_on: charge["cancelled_on"], expires_on: charge["expires_on"], plan_id: plan_id, description: charge["description"], shop_domain: charge["shop_domain"], created_at: charge["created_at"], updated_at: charge["updated_at"], sync: 0, process_type: 'store-charge')
490
688
  message = {"message" => 'success'}
491
689
  rescue Exception => e
492
690
  Rollbar.error("Charge not saved on local DB due to #{e.inspect}")
@@ -506,12 +704,32 @@ module AppManager
506
704
  return message
507
705
  end
508
706
 
707
+ def store_discount_used(params,options)
708
+ if options && options[:shop_domain].present? && options[:discount_id].present?
709
+ app_id = AppManager::Discount.where(discount_id: options[:discount_id])
710
+ .pluck(:app_id)
711
+ .first rescue nil
712
+ data = {
713
+ 'discount_id' => options[:discount_id],
714
+ 'domain' => options[:shop_domain],
715
+ 'sync' => false,
716
+ 'process_type' => 'use-discount',
717
+ 'app_id' => app_id
718
+ }
719
+ discount_usage_log = AppManager::DiscountUsageLog.create(data)
720
+ return { 'message' => discount_usage_log ? 'success' : 'fail' }
721
+ else
722
+ return {"message" => 'fail'}
723
+ end
724
+ end
725
+
509
726
 
510
727
  def sync_app_manager
511
728
  plan_obj = AppManager::Client.new
512
729
  response = plan_obj.get_status
513
730
  if response && response.code == 200
514
731
  charges = AppManager::Charge.where(sync: false)
732
+ discounts_usage_logs = AppManager::DiscountUsageLog.where(sync: false, process_type: 'use-discount')
515
733
  charges.each do |charge|
516
734
  if charge
517
735
  if !charge["cancelled_on"].nil?
@@ -524,6 +742,17 @@ module AppManager
524
742
  end
525
743
  end
526
744
  end
745
+
746
+ if discounts_usage_logs.any?
747
+ discounts_usage_logs.each do |discount_usage_log|
748
+ discount_obj = AppManager::Client.new
749
+ discount_response = discount_obj.sync_discount_usage_log(shop_domain: discount_usage_log['domain'], discount_id: discount_usage_log['discount_id'].to_i)
750
+ if discount_response && discount_response["data"] == "Saved"
751
+ AppManager::DiscountUsageLog.find_by(discount_id: discount_usage_log['discount_id'],sync: false).update(sync: true, process_type: nil)
752
+ end
753
+ end
754
+ end
755
+
527
756
  end
528
757
  end
529
758
 
@@ -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
- Rollbar.error("=== 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_key}, api_version=#{@api_version}, shopify_domain=#{@shopify_domain}, shopify_token ===#{@shopify_token}")
37
37
  return []
38
38
  end
39
39
  end
@@ -54,7 +54,7 @@ module AppManager
54
54
  end
55
55
 
56
56
 
57
- def recurring_charge_api_call(plan,return_url,shop)
57
+ def recurring_charge_api_call(plan,return_url,shop,discount_cookie)
58
58
  plan_test = nil
59
59
  shop_plan_field = AppManager.configuration.field_names['shopify_plan'] rescue nil
60
60
  if !plan['affiliate'].nil? && plan['affiliate'].any? && !shop_plan_field.nil? && plan['affiliate'].map{|e| e['value']}.include?(shop[shop_plan_field])
@@ -67,6 +67,7 @@ module AppManager
67
67
  remaining_obj = AppManager::Client.new
68
68
  remaining = remaining_obj.get_remaining_days(shop.shopify_domain,trial_activated_at,plan_id_field)
69
69
  # trial_days = !remaining.nil? ? remaining : trial_days
70
+
70
71
  if !remaining.nil?
71
72
  if !plan_id_field.nil?
72
73
  plan_obj = AppManager::Client.new
@@ -82,15 +83,73 @@ module AppManager
82
83
  end
83
84
  end
84
85
 
85
- discount_type = plan['discount_type'] || "percentage"
86
- discount_val = discount_type == "percentage" ? (plan['discount'].to_f/ 100) : "#{plan['discount']}"
87
- plan_discount = plan['discount'] ? { "discount" => { "durationLimitInIntervals" => (plan['cycle_count'].to_i || 0), "value" => {"#{discount_type}" => discount_val} } } : {}
86
+ promotional_discount = []
87
+ if discount_cookie && shop
88
+ created_at = shop[AppManager.configuration.field_names['created_at']]
89
+ reinstall = AppManager.check_if_reinstall(created_at)
90
+ plan_obj = AppManager::Client.new
91
+ promotional_discount = plan_obj.get_promotional_discount(shop.shopify_domain, discount_cookie['codeType'], discount_cookie['code'], reinstall)
92
+ promotional_discount = [] if promotional_discount.class.to_s == "Hash" && promotional_discount.has_key?('status') && promotional_discount['status'] == 404
93
+ end
94
+
95
+ if !plan['discount'].nil? && plan['discount'] != 0
96
+ discount_type = plan['discount_type'] || "percentage"
97
+ discount_val = discount_type == "percentage" ? (plan['discount'].to_f/ 100) : "#{plan['discount']}"
98
+ if !@api_version.nil? && @api_version.to_s.include?('2024')
99
+ plan_discount = if plan['discount'] && plan['cycle_count']
100
+ {
101
+ "discount" => { "durationLimitInIntervals" => (plan['cycle_count'].to_i),
102
+ "value" => {"#{discount_type}" => discount_val}
103
+ }
104
+ }
105
+ elsif plan['discount']
106
+ {
107
+ "discount" => { "value" => {"#{discount_type}" => discount_val}
108
+ }
109
+ }
110
+ else
111
+ {}
112
+ end
113
+ else
114
+ plan_discount = plan['discount'] ? { "discount" => { "durationLimitInIntervals" => (plan['cycle_count'].to_i), "value" => {"#{discount_type}" => discount_val} } } : {}
115
+ end
116
+ else
117
+
118
+ if promotional_discount.any?
119
+
120
+ if promotional_discount['plan_relation'].any? && !promotional_discount['plan_relation'].include?(plan['id'])
121
+ plan_discount = {}
122
+ else
123
+
124
+ discount_type = promotional_discount['type'] || 'percentage'
125
+ discount_value = {
126
+ discount_type => discount_type == 'percentage' ? promotional_discount['value'].to_f / 100 : [promotional_discount['value'].to_f, plan['price']].min
127
+ }
128
+
129
+ discount = { 'value' => discount_value }
130
+
131
+ discount['durationLimitInIntervals'] = promotional_discount['duration_intervals'].to_i if promotional_discount['duration_intervals'].to_i.positive?
132
+ plan_discount = { "discount" => discount}
133
+
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+
140
+ discount_exists = !plan['discount'].nil? && plan['discount'] != 0
141
+ promotional_discount_applies = promotional_discount.present? && promotional_discount.any?
142
+ promotional_discount_id = discount_exists && promotional_discount_applies ? 0 : promotional_discount_applies ? promotional_discount['id'] : 0
143
+
144
+ plans_relation = promotional_discount.present? && promotional_discount['plan_relation'].any? ? promotional_discount['plan_relation'] : []
145
+ # Append additional data to the existing return_url
146
+ return_url += "&promo_discount=#{promotional_discount_id}&discounted_plans=#{Rack::Utils.escape(plans_relation.to_json)}"
88
147
 
89
148
  price_details = {
90
149
  "price": { "amount": plan['price'], "currencyCode": 'USD' },
91
150
  "interval": plan['interval']['value']
92
151
  }
93
- price_details.merge! plan_discount if plan_discount.any?
152
+ price_details.merge! plan_discount if plan_discount && plan_discount.any?
94
153
 
95
154
  plan_var = {
96
155
  "appRecurringPricingDetails": price_details,
@@ -0,0 +1,41 @@
1
+ # app/middleware/set_cookie_middleware.rb
2
+ require 'action_dispatch/middleware/cookies'
3
+ require 'uri'
4
+
5
+ # app/middleware/set_cookie.rb
6
+ module AppManager
7
+ class SetCookie
8
+ def initialize(app, condition)
9
+ @app = app
10
+ @condition = condition
11
+ end
12
+
13
+ def call(env)
14
+ request = Rack::Request.new(env)
15
+
16
+ if @condition.call(request)
17
+ url = URI.parse(request.url)
18
+ host = url.host
19
+ discount_code = request.path.split('/')[2]
20
+
21
+ # Set a cookie named 'ShopCircleDiscount' with the extracted values
22
+ lifetime = Time.now + 60 * 60 * 24 * 365
23
+ cookie_value = discount_code
24
+
25
+ AppManager.clear_cache #clearing cache
26
+ # Set a 302 response with an external URL and a cookie
27
+ return [
28
+ 302,
29
+ {
30
+ 'Location' => 'https://admin.shopify.com/admin/apps/'+ENV['SHOPIFY_APP_SLUG']+'/home/plan' ,
31
+ 'Set-Cookie' => "ShopCircleDiscount=#{cookie_value}; expires=#{lifetime.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')}; path=/; domain=#{host}; secure; HttpOnly; SameSite=None",
32
+ 'Content-Type' => 'text/plain'
33
+ },
34
+ ['Redirecting to external URL with cookie']
35
+ ]
36
+ end
37
+
38
+ @app.call(env)
39
+ end
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppManager
4
- VERSION = "1.6.3"
4
+ VERSION = "2.0.0"
5
5
  end
data/lib/app_manager.rb CHANGED
@@ -16,8 +16,25 @@ require "app_manager/model"
16
16
  require "app_manager/fail_safe"
17
17
  require 'app_manager/railtie' if defined?(Rails)
18
18
  require 'app_manager/exceptions'
19
+ require 'action_dispatch/middleware/cookies' if defined?(Rails)
20
+ require "action_controller"
19
21
 
20
22
  module AppManager
23
+ module CookiesHandler
24
+ include ActionController::Cookies
25
+
26
+ def self.resolve_from_cookies(request)
27
+ if request.cookies['ShopCircleDiscount'].present?
28
+ {
29
+ 'codeType' => 'normal',
30
+ 'code' => request.cookies['ShopCircleDiscount']
31
+ }
32
+ else
33
+ nil
34
+ end
35
+ end
36
+ end
37
+
21
38
  def self.configure
22
39
  yield configuration
23
40
  end
@@ -34,4 +51,14 @@ module AppManager
34
51
  end
35
52
  end
36
53
 
54
+ def self.resolve_from_cookies(request)
55
+ CookiesHandler.resolve_from_cookies(request)
56
+ end
57
+
58
+ def self.check_if_reinstall(created_at)
59
+ created_at < (Time.now - 5.minutes) ? 1 : 0
60
+ end
61
+
62
+
63
+
37
64
  end
@@ -39,6 +39,14 @@ module AppManager
39
39
  end
40
40
  end
41
41
 
42
+ def create_discount_table_migration
43
+ if self.class.migration_exists?("db/app_manager", "add_discount_tables")
44
+ say_status("skipped", "Migration add_discount_tables.rb already exists")
45
+ else
46
+ migration_template("add_discount_tables.erb", "db/app_manager/add_discount_tables.rb")
47
+ end
48
+ end
49
+
42
50
 
43
51
  private
44
52
 
@@ -0,0 +1,48 @@
1
+ class AddDiscountTables < ActiveRecord::Migration[<%= rails_migration_version %>]
2
+ def change
3
+ create_table :discounts do |t|
4
+ t.bigint :discount_id
5
+ t.string :name
6
+ t.string :code
7
+ t.string :discount_type, default: 'amount'
8
+ t.decimal :value, default: 0
9
+ t.integer :duration_intervals
10
+ t.integer :max_usage
11
+ t.boolean :enabled, default: true
12
+ t.datetime :valid_from
13
+ t.datetime :valid_to
14
+ t.integer :priority, default: 0
15
+ t.boolean :multiple_uses, default: true
16
+ t.boolean :multiple_apps, default: true
17
+ t.integer :app_id, default: 0
18
+ t.timestamps
19
+ t.datetime :deleted_at
20
+ end
21
+
22
+ create_table :discount_shops do |t|
23
+ t.bigint :discount_id, index: true, foreign_key: true
24
+ t.string :domain
25
+ end
26
+
27
+ create_table :discounts_usage_log do |t|
28
+ t.bigint :discount_id, index: true, foreign_key: true
29
+ t.bigint :app_id, index: true, foreign_key: true
30
+ t.string :domain
31
+ t.boolean :sync, default: true
32
+ t.string :process_type
33
+ t.timestamps
34
+ end
35
+
36
+ create_table :discount_link_plans do |t|
37
+ t.bigint :discount_id, index: true, foreign_key: true
38
+ t.bigint :plan_id, index: true, foreign_key: true
39
+ end
40
+ end
41
+
42
+ def down
43
+ drop_table :discounts
44
+ drop_table :discount_shops
45
+ drop_table :discounts_usage_log
46
+ drop_table :discount_link_plans
47
+ end
48
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: app_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rahul Tiwari @ Hulkapps
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-08 00:00:00.000000000 Z
11
+ date: 2024-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -89,7 +89,11 @@ files:
89
89
  - app/model/app_manager/app_manager_record.rb
90
90
  - app/model/app_manager/app_structure.rb
91
91
  - app/model/app_manager/charge.rb
92
+ - app/model/app_manager/discount.rb
93
+ - app/model/app_manager/discount_link_plan.rb
92
94
  - app/model/app_manager/discount_plan.rb
95
+ - app/model/app_manager/discount_shop.rb
96
+ - app/model/app_manager/discount_usage_log.rb
93
97
  - app/model/app_manager/extend_trial.rb
94
98
  - app/model/app_manager/plan.rb
95
99
  - app/model/app_manager/plan_user.rb
@@ -115,9 +119,11 @@ files:
115
119
  - lib/app_manager/protection.rb
116
120
  - lib/app_manager/railtie.rb
117
121
  - lib/app_manager/response_cache.rb
122
+ - lib/app_manager/set_cookie.rb
118
123
  - lib/app_manager/tasks/sync/local_app_manager.rake
119
124
  - lib/app_manager/version.rb
120
125
  - lib/generators/app_manager/install/install_generator.rb
126
+ - lib/generators/app_manager/install/templates/add_discount_tables.erb
121
127
  - lib/generators/app_manager/install/templates/add_external_charge_field.erb
122
128
  - lib/generators/app_manager/install/templates/add_plan_trial_grandfathered_to_shops.erb
123
129
  - lib/generators/app_manager/install/templates/app_manager.rb.tt