app_manager 1.7.0 → 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 +4 -4
- data/Gemfile.lock +67 -69
- data/README.md +36 -1
- data/app/controllers/app_manager/charges_controller.rb +21 -1
- data/app/controllers/app_manager/plans_controller.rb +13 -2
- data/app/model/app_manager/discount.rb +5 -0
- data/app/model/app_manager/discount_link_plan.rb +5 -0
- data/app/model/app_manager/discount_shop.rb +5 -0
- data/app/model/app_manager/discount_usage_log.rb +5 -0
- data/lib/app_manager/client/connection.rb +24 -4
- data/lib/app_manager/client/plans.rb +12 -0
- data/lib/app_manager/fail_safe.rb +227 -3
- data/lib/app_manager/graphql_helper.rb +62 -19
- data/lib/app_manager/set_cookie.rb +41 -0
- data/lib/app_manager/version.rb +1 -1
- data/lib/app_manager.rb +27 -0
- data/lib/generators/app_manager/install/install_generator.rb +8 -0
- data/lib/generators/app_manager/install/templates/add_discount_tables.erb +48 -0
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1093f4ae3ee06a00f81bf11ad98bb1669f6b9f931bed69a430525733058143a0
|
|
4
|
+
data.tar.gz: 9a3a425bdf82d12982f33ace1e86a1e5b47bbc7b3430ccd96b0469967cbf2f65
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 (
|
|
4
|
+
app_manager (2.0.0)
|
|
5
5
|
activerecord-import (~> 1.4)
|
|
6
6
|
httparty
|
|
7
7
|
kaminari (>= 0.16.3)
|
|
@@ -10,35 +10,35 @@ PATH
|
|
|
10
10
|
GEM
|
|
11
11
|
remote: https://rubygems.org/
|
|
12
12
|
specs:
|
|
13
|
-
actioncable (7.1.2)
|
|
14
|
-
actionpack (= 7.1.2)
|
|
15
|
-
activesupport (= 7.1.2)
|
|
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
18
|
zeitwerk (~> 2.6)
|
|
19
|
-
actionmailbox (7.1.2)
|
|
20
|
-
actionpack (= 7.1.2)
|
|
21
|
-
activejob (= 7.1.2)
|
|
22
|
-
activerecord (= 7.1.2)
|
|
23
|
-
activestorage (= 7.1.2)
|
|
24
|
-
activesupport (= 7.1.2)
|
|
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)
|
|
25
25
|
mail (>= 2.7.1)
|
|
26
26
|
net-imap
|
|
27
27
|
net-pop
|
|
28
28
|
net-smtp
|
|
29
|
-
actionmailer (7.1.2)
|
|
30
|
-
actionpack (= 7.1.2)
|
|
31
|
-
actionview (= 7.1.2)
|
|
32
|
-
activejob (= 7.1.2)
|
|
33
|
-
activesupport (= 7.1.2)
|
|
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)
|
|
34
34
|
mail (~> 2.5, >= 2.5.4)
|
|
35
35
|
net-imap
|
|
36
36
|
net-pop
|
|
37
37
|
net-smtp
|
|
38
38
|
rails-dom-testing (~> 2.2)
|
|
39
|
-
actionpack (7.1.2)
|
|
40
|
-
actionview (= 7.1.2)
|
|
41
|
-
activesupport (= 7.1.2)
|
|
39
|
+
actionpack (7.1.3.2)
|
|
40
|
+
actionview (= 7.1.3.2)
|
|
41
|
+
activesupport (= 7.1.3.2)
|
|
42
42
|
nokogiri (>= 1.8.5)
|
|
43
43
|
racc
|
|
44
44
|
rack (>= 2.2.4)
|
|
@@ -46,37 +46,37 @@ GEM
|
|
|
46
46
|
rack-test (>= 0.6.3)
|
|
47
47
|
rails-dom-testing (~> 2.2)
|
|
48
48
|
rails-html-sanitizer (~> 1.6)
|
|
49
|
-
actiontext (7.1.2)
|
|
50
|
-
actionpack (= 7.1.2)
|
|
51
|
-
activerecord (= 7.1.2)
|
|
52
|
-
activestorage (= 7.1.2)
|
|
53
|
-
activesupport (= 7.1.2)
|
|
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)
|
|
54
54
|
globalid (>= 0.6.0)
|
|
55
55
|
nokogiri (>= 1.8.5)
|
|
56
|
-
actionview (7.1.2)
|
|
57
|
-
activesupport (= 7.1.2)
|
|
56
|
+
actionview (7.1.3.2)
|
|
57
|
+
activesupport (= 7.1.3.2)
|
|
58
58
|
builder (~> 3.1)
|
|
59
59
|
erubi (~> 1.11)
|
|
60
60
|
rails-dom-testing (~> 2.2)
|
|
61
61
|
rails-html-sanitizer (~> 1.6)
|
|
62
|
-
activejob (7.1.2)
|
|
63
|
-
activesupport (= 7.1.2)
|
|
62
|
+
activejob (7.1.3.2)
|
|
63
|
+
activesupport (= 7.1.3.2)
|
|
64
64
|
globalid (>= 0.3.6)
|
|
65
|
-
activemodel (7.1.2)
|
|
66
|
-
activesupport (= 7.1.2)
|
|
67
|
-
activerecord (7.1.2)
|
|
68
|
-
activemodel (= 7.1.2)
|
|
69
|
-
activesupport (= 7.1.2)
|
|
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
70
|
timeout (>= 0.4.0)
|
|
71
71
|
activerecord-import (1.5.1)
|
|
72
72
|
activerecord (>= 4.2)
|
|
73
|
-
activestorage (7.1.2)
|
|
74
|
-
actionpack (= 7.1.2)
|
|
75
|
-
activejob (= 7.1.2)
|
|
76
|
-
activerecord (= 7.1.2)
|
|
77
|
-
activesupport (= 7.1.2)
|
|
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)
|
|
78
78
|
marcel (~> 1.0)
|
|
79
|
-
activesupport (7.1.2)
|
|
79
|
+
activesupport (7.1.3.2)
|
|
80
80
|
base64
|
|
81
81
|
bigdecimal
|
|
82
82
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
@@ -89,10 +89,10 @@ GEM
|
|
|
89
89
|
addressable (2.8.0)
|
|
90
90
|
public_suffix (>= 2.0.2, < 5.0)
|
|
91
91
|
base64 (0.2.0)
|
|
92
|
-
bigdecimal (3.1.
|
|
92
|
+
bigdecimal (3.1.6)
|
|
93
93
|
builder (3.2.4)
|
|
94
94
|
coderay (1.1.3)
|
|
95
|
-
concurrent-ruby (1.2.
|
|
95
|
+
concurrent-ruby (1.2.3)
|
|
96
96
|
connection_pool (2.4.1)
|
|
97
97
|
crack (0.4.5)
|
|
98
98
|
rexml
|
|
@@ -100,8 +100,7 @@ GEM
|
|
|
100
100
|
date (3.3.4)
|
|
101
101
|
diff-lcs (1.5.0)
|
|
102
102
|
dotenv (2.1.2)
|
|
103
|
-
drb (2.2.
|
|
104
|
-
ruby2_keywords
|
|
103
|
+
drb (2.2.1)
|
|
105
104
|
erubi (1.12.0)
|
|
106
105
|
globalid (1.2.1)
|
|
107
106
|
activesupport (>= 6.1)
|
|
@@ -109,12 +108,12 @@ GEM
|
|
|
109
108
|
httparty (0.21.0)
|
|
110
109
|
mini_mime (>= 1.0.0)
|
|
111
110
|
multi_xml (>= 0.5.2)
|
|
112
|
-
i18n (1.14.
|
|
111
|
+
i18n (1.14.4)
|
|
113
112
|
concurrent-ruby (~> 1.0)
|
|
114
|
-
io-console (0.7.
|
|
115
|
-
irb (1.
|
|
113
|
+
io-console (0.7.2)
|
|
114
|
+
irb (1.12.0)
|
|
116
115
|
rdoc
|
|
117
|
-
reline (>= 0.
|
|
116
|
+
reline (>= 0.4.2)
|
|
118
117
|
kaminari (1.2.2)
|
|
119
118
|
activesupport (>= 4.1.0)
|
|
120
119
|
kaminari-actionview (= 1.2.2)
|
|
@@ -135,11 +134,11 @@ GEM
|
|
|
135
134
|
net-imap
|
|
136
135
|
net-pop
|
|
137
136
|
net-smtp
|
|
138
|
-
marcel (1.0.
|
|
137
|
+
marcel (1.0.4)
|
|
139
138
|
method_source (1.0.0)
|
|
140
139
|
mini_mime (1.1.5)
|
|
141
140
|
mini_portile2 (2.8.5)
|
|
142
|
-
minitest (5.
|
|
141
|
+
minitest (5.22.2)
|
|
143
142
|
multi_xml (0.6.0)
|
|
144
143
|
mutex_m (0.2.0)
|
|
145
144
|
net-imap (0.3.7)
|
|
@@ -162,7 +161,7 @@ GEM
|
|
|
162
161
|
stringio
|
|
163
162
|
public_suffix (4.0.6)
|
|
164
163
|
racc (1.7.3)
|
|
165
|
-
rack (3.0.
|
|
164
|
+
rack (3.0.9.1)
|
|
166
165
|
rack-session (2.0.0)
|
|
167
166
|
rack (>= 3.0.0)
|
|
168
167
|
rack-test (2.1.0)
|
|
@@ -170,20 +169,20 @@ GEM
|
|
|
170
169
|
rackup (2.1.0)
|
|
171
170
|
rack (>= 3)
|
|
172
171
|
webrick (~> 1.8)
|
|
173
|
-
rails (7.1.2)
|
|
174
|
-
actioncable (= 7.1.2)
|
|
175
|
-
actionmailbox (= 7.1.2)
|
|
176
|
-
actionmailer (= 7.1.2)
|
|
177
|
-
actionpack (= 7.1.2)
|
|
178
|
-
actiontext (= 7.1.2)
|
|
179
|
-
actionview (= 7.1.2)
|
|
180
|
-
activejob (= 7.1.2)
|
|
181
|
-
activemodel (= 7.1.2)
|
|
182
|
-
activerecord (= 7.1.2)
|
|
183
|
-
activestorage (= 7.1.2)
|
|
184
|
-
activesupport (= 7.1.2)
|
|
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)
|
|
185
184
|
bundler (>= 1.15.0)
|
|
186
|
-
railties (= 7.1.2)
|
|
185
|
+
railties (= 7.1.3.2)
|
|
187
186
|
rails-dom-testing (2.2.0)
|
|
188
187
|
activesupport (>= 5.0.0)
|
|
189
188
|
minitest
|
|
@@ -191,9 +190,9 @@ GEM
|
|
|
191
190
|
rails-html-sanitizer (1.6.0)
|
|
192
191
|
loofah (~> 2.21)
|
|
193
192
|
nokogiri (~> 1.14)
|
|
194
|
-
railties (7.1.2)
|
|
195
|
-
actionpack (= 7.1.2)
|
|
196
|
-
activesupport (= 7.1.2)
|
|
193
|
+
railties (7.1.3.2)
|
|
194
|
+
actionpack (= 7.1.3.2)
|
|
195
|
+
activesupport (= 7.1.3.2)
|
|
197
196
|
irb
|
|
198
197
|
rackup (>= 1.0.0)
|
|
199
198
|
rake (>= 12.2)
|
|
@@ -202,7 +201,7 @@ GEM
|
|
|
202
201
|
rake (13.0.6)
|
|
203
202
|
rdoc (6.6.2)
|
|
204
203
|
psych (>= 4.0.0)
|
|
205
|
-
reline (0.4.
|
|
204
|
+
reline (0.4.3)
|
|
206
205
|
io-console (~> 0.5)
|
|
207
206
|
rexml (3.2.5)
|
|
208
207
|
rspec (3.11.0)
|
|
@@ -220,9 +219,8 @@ GEM
|
|
|
220
219
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
221
220
|
rspec-support (~> 3.11.0)
|
|
222
221
|
rspec-support (3.11.0)
|
|
223
|
-
ruby2_keywords (0.0.5)
|
|
224
222
|
stringio (3.1.0)
|
|
225
|
-
thor (1.3.
|
|
223
|
+
thor (1.3.1)
|
|
226
224
|
timeout (0.4.1)
|
|
227
225
|
tzinfo (2.0.6)
|
|
228
226
|
concurrent-ruby (~> 1.0)
|
|
@@ -234,7 +232,7 @@ GEM
|
|
|
234
232
|
websocket-driver (0.7.6)
|
|
235
233
|
websocket-extensions (>= 0.1.0)
|
|
236
234
|
websocket-extensions (0.1.5)
|
|
237
|
-
zeitwerk (2.6.
|
|
235
|
+
zeitwerk (2.6.13)
|
|
238
236
|
|
|
239
237
|
PLATFORMS
|
|
240
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,9 +58,12 @@ 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)
|
|
66
|
+
data = gq_obj.recurring_charge_api_call(plan_data, return_url, @shop,discount_cookie)
|
|
64
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}
|
|
@@ -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)
|
|
@@ -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 :
|
|
32
|
-
|
|
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
|
-
|
|
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:
|
|
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("[
|
|
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::
|
|
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
|
|
|
@@ -481,6 +612,68 @@ module AppManager
|
|
|
481
612
|
|
|
482
613
|
end
|
|
483
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
|
+
|
|
484
677
|
def store_local_charge(params, options)
|
|
485
678
|
message = {"message" => 'fail'}
|
|
486
679
|
if options
|
|
@@ -491,7 +684,7 @@ module AppManager
|
|
|
491
684
|
test_value = charge["test"]
|
|
492
685
|
plan_id = charge["plan_id"].to_i
|
|
493
686
|
begin
|
|
494
|
-
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')
|
|
495
688
|
message = {"message" => 'success'}
|
|
496
689
|
rescue Exception => e
|
|
497
690
|
Rollbar.error("Charge not saved on local DB due to #{e.inspect}")
|
|
@@ -511,12 +704,32 @@ module AppManager
|
|
|
511
704
|
return message
|
|
512
705
|
end
|
|
513
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
|
+
|
|
514
726
|
|
|
515
727
|
def sync_app_manager
|
|
516
728
|
plan_obj = AppManager::Client.new
|
|
517
729
|
response = plan_obj.get_status
|
|
518
730
|
if response && response.code == 200
|
|
519
731
|
charges = AppManager::Charge.where(sync: false)
|
|
732
|
+
discounts_usage_logs = AppManager::DiscountUsageLog.where(sync: false, process_type: 'use-discount')
|
|
520
733
|
charges.each do |charge|
|
|
521
734
|
if charge
|
|
522
735
|
if !charge["cancelled_on"].nil?
|
|
@@ -529,6 +742,17 @@ module AppManager
|
|
|
529
742
|
end
|
|
530
743
|
end
|
|
531
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
|
+
|
|
532
756
|
end
|
|
533
757
|
end
|
|
534
758
|
|
|
@@ -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,31 +83,73 @@ module AppManager
|
|
|
82
83
|
end
|
|
83
84
|
end
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
+
}
|
|
97
104
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
102
116
|
else
|
|
103
|
-
|
|
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
|
+
|
|
104
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)}"
|
|
147
|
+
|
|
105
148
|
price_details = {
|
|
106
149
|
"price": { "amount": plan['price'], "currencyCode": 'USD' },
|
|
107
150
|
"interval": plan['interval']['value']
|
|
108
151
|
}
|
|
109
|
-
price_details.merge! plan_discount if plan_discount.any?
|
|
152
|
+
price_details.merge! plan_discount if plan_discount && plan_discount.any?
|
|
110
153
|
|
|
111
154
|
plan_var = {
|
|
112
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
|
data/lib/app_manager/version.rb
CHANGED
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:
|
|
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: 2024-
|
|
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
|