app_manager 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b537020a68cfa232a0ad374777b2a3a9317d5aa599da985ac07334814567d321
4
- data.tar.gz: e89d2d9140a3196468d77b5bed6e014e3cabde20478c5206c29fc47e3322b9e9
3
+ metadata.gz: 92d071e3e478e20f2fb063d5a821be4d772edb68de15c862c50f0a01c69727d8
4
+ data.tar.gz: 1e171148960d955ca01c76a7bf715630508e2766e4a46790a85e86ffba4ea7a1
5
5
  SHA512:
6
- metadata.gz: 95d3718467208b590e9889a5b774da042a257b7e8f8d05f15b2317637b490b6399bdbe8467fad02226b651d9c7119e805f0e031658202f2f439c9a8dff836111
7
- data.tar.gz: aaeee10fb9e7e7edeb4c743ce2bb3df1b5c332f42386a6d87b866d9e33da2a06ba74e45cb7888da1ea97ca581a48291ae373c49ea1e93cbf7c9e6322337c2ada
6
+ metadata.gz: 205c194f35ab5df4a9fab9fe374a1e83c89ff5ca2ceaa8327ae6ca92589343522ba8c35bdac61d63c92932d9dd7b5769410d4975c8b7fc191e9fcbcf6df4ba61
7
+ data.tar.gz: b8f6a607d5f1a71e5d0b2537909a87a771718b5f31bbe2d39d3ae291521e40eac5b807c2749806f6c20f1bc19453c6e04ebf52533e69c490441f6d9b33ca8b3d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- app_manager (1.1.0)
4
+ app_manager (1.1.1)
5
5
  httparty
6
6
  kaminari (>= 0.16.3)
7
7
  rails (>= 5.2.0)
@@ -10,67 +10,67 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- actioncable (7.0.2.3)
14
- actionpack (= 7.0.2.3)
15
- activesupport (= 7.0.2.3)
13
+ actioncable (7.0.3)
14
+ actionpack (= 7.0.3)
15
+ activesupport (= 7.0.3)
16
16
  nio4r (~> 2.0)
17
17
  websocket-driver (>= 0.6.1)
18
- actionmailbox (7.0.2.3)
19
- actionpack (= 7.0.2.3)
20
- activejob (= 7.0.2.3)
21
- activerecord (= 7.0.2.3)
22
- activestorage (= 7.0.2.3)
23
- activesupport (= 7.0.2.3)
18
+ actionmailbox (7.0.3)
19
+ actionpack (= 7.0.3)
20
+ activejob (= 7.0.3)
21
+ activerecord (= 7.0.3)
22
+ activestorage (= 7.0.3)
23
+ activesupport (= 7.0.3)
24
24
  mail (>= 2.7.1)
25
25
  net-imap
26
26
  net-pop
27
27
  net-smtp
28
- actionmailer (7.0.2.3)
29
- actionpack (= 7.0.2.3)
30
- actionview (= 7.0.2.3)
31
- activejob (= 7.0.2.3)
32
- activesupport (= 7.0.2.3)
28
+ actionmailer (7.0.3)
29
+ actionpack (= 7.0.3)
30
+ actionview (= 7.0.3)
31
+ activejob (= 7.0.3)
32
+ activesupport (= 7.0.3)
33
33
  mail (~> 2.5, >= 2.5.4)
34
34
  net-imap
35
35
  net-pop
36
36
  net-smtp
37
37
  rails-dom-testing (~> 2.0)
38
- actionpack (7.0.2.3)
39
- actionview (= 7.0.2.3)
40
- activesupport (= 7.0.2.3)
38
+ actionpack (7.0.3)
39
+ actionview (= 7.0.3)
40
+ activesupport (= 7.0.3)
41
41
  rack (~> 2.0, >= 2.2.0)
42
42
  rack-test (>= 0.6.3)
43
43
  rails-dom-testing (~> 2.0)
44
44
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
45
- actiontext (7.0.2.3)
46
- actionpack (= 7.0.2.3)
47
- activerecord (= 7.0.2.3)
48
- activestorage (= 7.0.2.3)
49
- activesupport (= 7.0.2.3)
45
+ actiontext (7.0.3)
46
+ actionpack (= 7.0.3)
47
+ activerecord (= 7.0.3)
48
+ activestorage (= 7.0.3)
49
+ activesupport (= 7.0.3)
50
50
  globalid (>= 0.6.0)
51
51
  nokogiri (>= 1.8.5)
52
- actionview (7.0.2.3)
53
- activesupport (= 7.0.2.3)
52
+ actionview (7.0.3)
53
+ activesupport (= 7.0.3)
54
54
  builder (~> 3.1)
55
55
  erubi (~> 1.4)
56
56
  rails-dom-testing (~> 2.0)
57
57
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
58
- activejob (7.0.2.3)
59
- activesupport (= 7.0.2.3)
58
+ activejob (7.0.3)
59
+ activesupport (= 7.0.3)
60
60
  globalid (>= 0.3.6)
61
- activemodel (7.0.2.3)
62
- activesupport (= 7.0.2.3)
63
- activerecord (7.0.2.3)
64
- activemodel (= 7.0.2.3)
65
- activesupport (= 7.0.2.3)
66
- activestorage (7.0.2.3)
67
- actionpack (= 7.0.2.3)
68
- activejob (= 7.0.2.3)
69
- activerecord (= 7.0.2.3)
70
- activesupport (= 7.0.2.3)
61
+ activemodel (7.0.3)
62
+ activesupport (= 7.0.3)
63
+ activerecord (7.0.3)
64
+ activemodel (= 7.0.3)
65
+ activesupport (= 7.0.3)
66
+ activestorage (7.0.3)
67
+ actionpack (= 7.0.3)
68
+ activejob (= 7.0.3)
69
+ activerecord (= 7.0.3)
70
+ activesupport (= 7.0.3)
71
71
  marcel (~> 1.0)
72
72
  mini_mime (>= 1.1.0)
73
- activesupport (7.0.2.3)
73
+ activesupport (7.0.3)
74
74
  concurrent-ruby (~> 1.0, >= 1.0.2)
75
75
  i18n (>= 1.6, < 2)
76
76
  minitest (>= 5.1)
@@ -95,7 +95,6 @@ GEM
95
95
  multi_xml (>= 0.5.2)
96
96
  i18n (1.10.0)
97
97
  concurrent-ruby (~> 1.0)
98
- io-wait (0.2.1)
99
98
  kaminari (1.2.2)
100
99
  activesupport (>= 4.1.0)
101
100
  kaminari-actionview (= 1.2.2)
@@ -108,7 +107,7 @@ GEM
108
107
  activerecord
109
108
  kaminari-core (= 1.2.2)
110
109
  kaminari-core (1.2.2)
111
- loofah (2.15.0)
110
+ loofah (2.18.0)
112
111
  crass (~> 1.0.2)
113
112
  nokogiri (>= 1.5.9)
114
113
  mail (2.7.1)
@@ -120,7 +119,7 @@ GEM
120
119
  mime-types-data (3.2022.0105)
121
120
  mini_mime (1.1.2)
122
121
  mini_portile2 (2.8.0)
123
- minitest (5.15.0)
122
+ minitest (5.16.0)
124
123
  multi_xml (0.6.0)
125
124
  net-imap (0.2.3)
126
125
  digest
@@ -130,47 +129,48 @@ GEM
130
129
  digest
131
130
  net-protocol
132
131
  timeout
133
- net-protocol (0.1.2)
134
- io-wait
132
+ net-protocol (0.1.3)
135
133
  timeout
136
134
  net-smtp (0.3.1)
137
135
  digest
138
136
  net-protocol
139
137
  timeout
140
138
  nio4r (2.5.8)
141
- nokogiri (1.13.3)
139
+ nokogiri (1.13.6)
142
140
  mini_portile2 (~> 2.8.0)
143
141
  racc (~> 1.4)
142
+ nokogiri (1.13.6-x86_64-linux)
143
+ racc (~> 1.4)
144
144
  pry (0.14.1)
145
145
  coderay (~> 1.1)
146
146
  method_source (~> 1.0)
147
147
  public_suffix (4.0.6)
148
148
  racc (1.6.0)
149
- rack (2.2.3)
149
+ rack (2.2.3.1)
150
150
  rack-test (1.1.0)
151
151
  rack (>= 1.0, < 3)
152
- rails (7.0.2.3)
153
- actioncable (= 7.0.2.3)
154
- actionmailbox (= 7.0.2.3)
155
- actionmailer (= 7.0.2.3)
156
- actionpack (= 7.0.2.3)
157
- actiontext (= 7.0.2.3)
158
- actionview (= 7.0.2.3)
159
- activejob (= 7.0.2.3)
160
- activemodel (= 7.0.2.3)
161
- activerecord (= 7.0.2.3)
162
- activestorage (= 7.0.2.3)
163
- activesupport (= 7.0.2.3)
152
+ rails (7.0.3)
153
+ actioncable (= 7.0.3)
154
+ actionmailbox (= 7.0.3)
155
+ actionmailer (= 7.0.3)
156
+ actionpack (= 7.0.3)
157
+ actiontext (= 7.0.3)
158
+ actionview (= 7.0.3)
159
+ activejob (= 7.0.3)
160
+ activemodel (= 7.0.3)
161
+ activerecord (= 7.0.3)
162
+ activestorage (= 7.0.3)
163
+ activesupport (= 7.0.3)
164
164
  bundler (>= 1.15.0)
165
- railties (= 7.0.2.3)
165
+ railties (= 7.0.3)
166
166
  rails-dom-testing (2.0.3)
167
167
  activesupport (>= 4.2.0)
168
168
  nokogiri (>= 1.6)
169
- rails-html-sanitizer (1.4.2)
169
+ rails-html-sanitizer (1.4.3)
170
170
  loofah (~> 2.3)
171
- railties (7.0.2.3)
172
- actionpack (= 7.0.2.3)
173
- activesupport (= 7.0.2.3)
171
+ railties (7.0.3)
172
+ actionpack (= 7.0.3)
173
+ activesupport (= 7.0.3)
174
174
  method_source
175
175
  rake (>= 12.2)
176
176
  thor (~> 1.0)
@@ -193,9 +193,9 @@ GEM
193
193
  rspec-support (~> 3.11.0)
194
194
  rspec-support (3.11.0)
195
195
  sqlite3 (1.3.13)
196
- strscan (3.0.1)
196
+ strscan (3.0.3)
197
197
  thor (1.2.1)
198
- timeout (0.2.0)
198
+ timeout (0.3.0)
199
199
  tzinfo (2.0.4)
200
200
  concurrent-ruby (~> 1.0)
201
201
  webmock (3.14.0)
@@ -205,7 +205,7 @@ GEM
205
205
  websocket-driver (0.7.5)
206
206
  websocket-extensions (>= 0.1.0)
207
207
  websocket-extensions (0.1.5)
208
- zeitwerk (2.5.4)
208
+ zeitwerk (2.6.0)
209
209
 
210
210
  PLATFORMS
211
211
  ruby
data/README.md CHANGED
@@ -28,6 +28,10 @@ gem 'app_manager'
28
28
 
29
29
  this install command will mount routes in your rails route and will create a config file at ```config/initializers/app_manager.rb```
30
30
 
31
+ ```
32
+ rails db:migrate
33
+ ```
34
+
31
35
 
32
36
  <a name="step2"></a>
33
37
  ### Configuration
@@ -35,18 +39,7 @@ gem 'app_manager'
35
39
  * Set Shopify API version to 2022-04 as app_manager is best compatible with this version.
36
40
 
37
41
 
38
- * Please check the 'shops' table that must have 'plan_id' as int/bigint and 'trial_activated_at' as datetime otherwise add its migration like following example:
39
-
40
- ```
41
- class AddPlanIdToShops < ActiveRecord::Migration[5.2]
42
- def change
43
- add_column :shops, :plan_id, :bigint
44
- add_column :shops, :trial_activated_at, :datetime
45
- end
46
- end
47
- ```
48
-
49
- and map these new fields in 'config.field_names' in below initializer file which is generated by install command. Please note: this is important step.
42
+ * Please map new fields (which added by app manager migration) in 'config.field_names' in below initializer file which is generated by install command. Please note: this is important step.
50
43
 
51
44
 
52
45
  * Please update blank fields in initializer file. Please copy 'uuid' from this [file](https://docs.google.com/spreadsheets/d/1cw2nSKxAHTGn4Cfa98RNdtfHT3zdtwu9bQD7s7hErXc/edit#gid=0) and paste in the following file and make sure that is unique per feature. After copying put your 'app name' next to 'uuid' column in this [file](https://docs.google.com/spreadsheets/d/1cw2nSKxAHTGn4Cfa98RNdtfHT3zdtwu9bQD7s7hErXc/edit#gid=0).
@@ -66,10 +59,11 @@ AppManager.configure do |config|
66
59
  'name' => 'shopify_domain', # demo-rahul-tiwari.myshopify.com
67
60
  'shopify_email' => 'email', # rahul.t@hulkapps.com
68
61
  'shopify_token' => 'shopify_token',
69
- 'shopify_plan' => 'plan_name', # partner_test
62
+ 'shopify_plan' => 'shopify_plan', # partner_test
70
63
  'plan_id' => 'plan_id', # 1. t
71
64
  'created_at' => 'created_at', # 2022-04-15 10:43:05
72
- 'trial_activated_at' => 'trial_activated_at' # field name that stores trial start/activated date
65
+ 'trial_activated_at' => 'trial_activated_at', # field name that stores trial start/activated date
66
+ 'grandfathered' => 'grandfathered'
73
67
  }
74
68
  config.plan_features = [
75
69
  {
@@ -79,7 +73,10 @@ AppManager.configure do |config|
79
73
  "description" => "Feature Description",
80
74
  "value_type" => "integer",
81
75
  "format" => "count",
82
- "display_order" => 1
76
+ "display_order" => 1,
77
+ "hidden_feature" => false,
78
+ "group_order" => "1",
79
+ "group" => "Group Name",
83
80
  },
84
81
  {
85
82
  "uuid" => "9f18f95a-bfaf-11ec-9d64-0242ac120002",
@@ -88,7 +85,10 @@ AppManager.configure do |config|
88
85
  "description" => "Feature Description",
89
86
  "value_type" => "boolean",
90
87
  "format" => "percentage",
91
- "display_order" => 2
88
+ "display_order" => 2,
89
+ "hidden_feature" => false,
90
+ "group_order" => "1",
91
+ "group" => "Group Name",
92
92
  },
93
93
  {
94
94
  "uuid" => "9f190a26-bfaf-11ec-9d64-0242ac120002",
@@ -97,7 +97,10 @@ AppManager.configure do |config|
97
97
  "description" => "Feature Description",
98
98
  "value_type" => "string",
99
99
  "format" => "string",
100
- "display_order" => 3
100
+ "display_order" => 3,
101
+ "hidden_feature" => false,
102
+ "group_order" => "1",
103
+ "group" => "Group Name",
101
104
  },
102
105
  {
103
106
  "uuid" => "9f191340-bfaf-11ec-9d64-0242ac12000",
@@ -110,10 +113,15 @@ AppManager.configure do |config|
110
113
  "val 2"
111
114
  ],
112
115
  "format" => "string",
113
- "display_order" => 4
116
+ "display_order" => 4,
117
+ "hidden_feature" => false,
118
+ "group_order" => "1",
119
+ "group" => "Group Name",
114
120
  }
115
- ] #Required, Values type : integer, boolean, string, array
121
+ ]
116
122
  end
123
+ #Required, Values type : integer, boolean, string, array #
124
+ #Format: percentage, count, string
117
125
  ```
118
126
 
119
127
 
@@ -159,6 +167,10 @@ and then you can use follwing methods with your shop objects.
159
167
  @shop.get_feature('feature-3') # provide slug of feature and this returns value of feature which is set in portal.
160
168
 
161
169
  @shop.get_remaining_days # return integer based on trial activated date.
170
+
171
+ @shop.get_plan # return integer based on trial activated date.
172
+
173
+ @shop.get_charge # return integer based on trial activated date.
162
174
  ```
163
175
 
164
176
 
@@ -1,12 +1,7 @@
1
1
  module AppManager
2
2
  class ApplicationController < ActionController::Base
3
3
  include AppManager::Actions
4
- cache_response_of_app_manager
5
4
  protect_from_forgery with: :exception
6
5
  include AppManager::Authenticate
7
- # rescue_from StandardError do |exception|
8
- # render json: { :error => exception.message }, :status => 500
9
- # end
10
-
11
6
  end
12
7
  end
@@ -2,6 +2,7 @@ require_dependency "app_manager/application_controller"
2
2
 
3
3
  module AppManager
4
4
  class BannersController < ApplicationController
5
+ cache_response_for :marketing_banner
5
6
  def marketing_banner
6
7
  begin
7
8
  banner_obj = AppManager::Client.new
@@ -1,5 +1,4 @@
1
1
  require_dependency "app_manager/application_controller"
2
-
3
2
  module AppManager
4
3
  class ChargesController < ApplicationController
5
4
  include HTTParty
@@ -23,16 +22,16 @@ module AppManager
23
22
  redirect_charge = data["data"]["appSubscriptionCreate"]["confirmationUrl"]
24
23
  render json: {'redirect_url' => redirect_charge}
25
24
  else
26
- render json: {'error' => data["errors"].as_json}
25
+ raise Error, "#{data["errors"].as_json}"
27
26
  end
28
27
  else
29
- render json: {'error' => data["errors"]}
28
+ raise Error, "#{data["errors"]}"
30
29
  end
31
30
  else
32
- render json: {'error' => 'Shop not found'}
31
+ raise ModelNotFound, "Shop not found"
33
32
  end
34
33
  else
35
- render json: {'error' => 'Missing Shop domain or plan id in params'}
34
+ raise Error, "Missing Shop domain or plan id in params"
36
35
  end
37
36
  end
38
37
 
@@ -65,22 +64,29 @@ module AppManager
65
64
 
66
65
  end
67
66
  end
67
+
68
68
  charge_ob = AppManager::Client.new(nil,json_req=true)
69
69
  response = charge_ob.store_charge(charge.to_json)
70
70
 
71
71
  if response['message'] == "success"
72
- model.update(@plan_field => params[:plan])
72
+ AppManager.clear_cache
73
+ model.update(@plan_field => params[:plan])
74
+ charge_data = plan_obj.get_charge(@shop[shopify_domain])
75
+ AppManager::EventHandler.new('charge_created',{
76
+ "plan" => plan_data,
77
+ "charge" => charge,
78
+ "previous_charge" => charge_data ? (charge_data['cancelled_charge'] || nil) : nil
79
+ })
73
80
  end
74
- redirect_to "/?shop=#{params[:shop]}"
81
+ redirect_to "#{app_url}?shop=#{params[:shop]}", :status => 301 and return
75
82
  else
76
-
77
- render json: {'error' => 'Invalid shopify charge'}
83
+ raise Error, "Invalid shopify charge #{charges.insect}"
78
84
  end
79
85
  else
80
- render json: {'error' => 'Shop not found'}
86
+ raise ModelNotFound, "Shop not found"
81
87
  end
82
88
  else
83
- render json: {'error' => 'Invalid params'}
89
+ raise Error, "Invalid params, must have charge_id,shop && plan"
84
90
  end
85
91
  end
86
92
 
@@ -2,6 +2,9 @@ require_dependency "app_manager/application_controller"
2
2
 
3
3
  module AppManager
4
4
  class PlansController < ApplicationController
5
+ cache_response_for :plans
6
+ cache_response_for :index
7
+ cache_response_for :users
5
8
  skip_before_action :verify_authenticity_token, :only => [:active_without_plan,:burst_cache,:fail_safe_backup]
6
9
  def index
7
10
  render :json => {"features" => AppManager.configuration.plan_features || []}
@@ -12,8 +15,9 @@ module AppManager
12
15
  active_plan_id_or_name = shopify_plan = plan = nil
13
16
  default_plan_id = nil
14
17
  plan_obj = AppManager::Client.new
15
- plans = plan_obj.get_plans
18
+ plans = []
16
19
  if params[:shop_domain].present? && !AppManager.configuration.plan_features.nil?
20
+ plans = plan_obj.get_plans(params[:shop_domain])
17
21
  @shop = shop_data
18
22
  if !@shop.nil?
19
23
  active_plan_id_or_name = @shop[@plan_field]
@@ -53,7 +57,7 @@ module AppManager
53
57
  end
54
58
 
55
59
  response = {
56
- 'plans' => plan_obj.get_plans,
60
+ 'plans' => plans,
57
61
  'shopify_plan' => shopify_plan,
58
62
  'plan' => plan,
59
63
  'default_plan_id' => default_plan_id
@@ -0,0 +1,10 @@
1
+ module AppManager
2
+
3
+ class EventHandler
4
+ def initialize(event,payload)
5
+ ActiveSupport::Notifications.instrument(event, payload)
6
+ end
7
+ end
8
+
9
+ end
10
+
@@ -2,8 +2,10 @@ module AppManager
2
2
  module Actions
3
3
  extend ActiveSupport::Concern
4
4
  module ClassMethods
5
- def cache_response_of_app_manager
6
- around_action ApiCacheHandler.new
5
+ def cache_response_for(*actions)
6
+ options = actions.extract_options!
7
+ filter_options = options.extract!(:if, :unless).merge(only: actions)
8
+ around_action ApiCacheHandler.new(options), filter_options
7
9
  end
8
10
  end
9
11
  end
@@ -1,8 +1,9 @@
1
1
  module AppManager
2
2
  module Actions
3
3
  class ApiCacheHandler
4
- def initialize
5
-
4
+ def initialize(options)
5
+ @options = options
6
+ @expires_in = @options[:expires_in]
6
7
  end
7
8
 
8
9
 
@@ -20,7 +21,7 @@ module AppManager
20
21
  protected
21
22
 
22
23
  def should_response_cache?
23
- return @request.get? && @response_cache.cached_response.present?
24
+ return @request.get? && AppManager.configuration.enable_caching && @response_cache.cached_response.present?
24
25
  end
25
26
 
26
27
  def log_info
@@ -37,29 +38,33 @@ module AppManager
37
38
 
38
39
  def cache_path
39
40
  @cache_path = "app-manager-cache"
40
-
41
- path_only = @request.fullpath.split('?').first
42
- @cache_path = "#{@cache_path}#{path_only}"
41
+ if @options[:cache_path].present?
42
+ @cache_path = "#{@cache_path}#{@options[:cache_path]}"
43
+ elsif AppManager.configuration.refresh_by_request_params?
44
+ @cache_path = "#{@cache_path}#{@request.fullpath}"
45
+ else
46
+ path_only = @request.fullpath.split('?').first
47
+ @cache_path = "#{@cache_path}#{path_only}"
48
+ end
43
49
 
44
50
  if AppManager.configuration.cache_by_headers.present?
45
51
  headers = AppManager.configuration.cache_by_headers.map do |header|
46
52
  @request.headers[header].to_s
47
53
  end
48
54
  headers_cache_path = headers.join('-')
49
- @cache_path = "#{@cache_path}/#{headers_cache_path}"
55
+ @cache_path = "#{@cache_path}#{headers_cache_path}"
50
56
  end
51
-
52
- @cache_path
57
+ return @cache_path
53
58
  end
54
59
 
55
60
  def render_cached_response
56
61
  body = @response_cache.body
57
62
  status = @response_cache.status
58
63
  headers = @response_cache.headers
59
- # headers.try(:each) do |key, value|
60
- # @controller.response.headers[key] = value
61
- # end
62
- @controller.render json: body, status: status
64
+ headers.try(:each) do |key, value|
65
+ @controller.response.headers[key] = value
66
+ end
67
+ @controller.render plain: body, status: status
63
68
  end
64
69
  end
65
70
  end
@@ -23,19 +23,24 @@ module AppManager
23
23
  private
24
24
 
25
25
  def request(http_method, path, options)
26
- response = self.class.send(http_method, path, { body: options })
27
- if path.include? "/get-status"
28
- data = response
29
- elsif path.include? "/sync-charge"
30
- data = response.parsed_response
31
- data = parse_data(response.parsed_response)
32
- else
33
- if response.code.to_s.start_with?('2') or response.code.to_s.start_with?('4')
34
- data = response.parsed_response
35
- data = parse_data(response.parsed_response)
26
+ begin
27
+ response = self.class.send(http_method, path, { body: options, timeout: 10 })
28
+ if path.include? "/get-status"
29
+ data = response
30
+ elsif path.include? "/sync-charge"
31
+ data = response.parsed_response
32
+ data = parse_data(response.parsed_response)
36
33
  else
37
- data = response_from_failsafe(path,options)
34
+ if response.code.to_s.start_with?('2') or response.code.to_s.start_with?('4')
35
+ data = response.parsed_response
36
+ data = parse_data(response.parsed_response)
37
+ # data = response_from_failsafe(path,options)
38
+ else
39
+ data = response_from_failsafe(path,options)
40
+ end
38
41
  end
42
+ rescue Exception => e
43
+ data = response_from_failsafe(path,options)
39
44
  end
40
45
  end
41
46
 
@@ -57,7 +62,7 @@ module AppManager
57
62
  when "static-contents"
58
63
  return @fs.get_local_app_structures
59
64
  when 'plans'
60
- return @fs.get_local_plans
65
+ return @fs.get_local_plans(params)
61
66
  when 'plan'
62
67
  return @fs.get_local_plan(params)
63
68
  when 'store-charge'
@@ -2,8 +2,8 @@ module AppManager
2
2
  class Client
3
3
  module Plans
4
4
 
5
- def get_plans(options = {})
6
- get("/plans", options)
5
+ def get_plans(shop_domain)
6
+ get("/plans?shop_domain=#{shop_domain}")
7
7
  end
8
8
 
9
9
  def get_plan(plan_id,shop_domain=nil)
@@ -12,10 +12,10 @@ module AppManager
12
12
  attr_accessor :shopify_domain_field
13
13
  attr_accessor :plan_id_or_name_field
14
14
  attr_accessor :field_names
15
-
16
-
15
+ attr_accessor :refresh_by_request_params
17
16
 
18
17
  def initialize
18
+ @refresh_by_request_params = true
19
19
  @expires_in = 1.day
20
20
  @enable_caching = true
21
21
  @app_url = nil
@@ -35,6 +35,7 @@ module AppManager
35
35
  'email' => 'email'
36
36
  }
37
37
  @fs = AppManager::FailSafe.new
38
+ AppManager.clear_cache
38
39
  end
39
40
 
40
41
  def expires_in
@@ -77,6 +78,9 @@ module AppManager
77
78
  @field_names
78
79
  end
79
80
 
81
+ def refresh_by_request_params?
82
+ @refresh_by_request_params
83
+ end
80
84
 
81
85
  end
82
86
  end
@@ -0,0 +1,4 @@
1
+ module AppManager
2
+ class Error < StandardError; end
3
+ class ModelNotFound < Error; end
4
+ end
@@ -11,53 +11,46 @@ module AppManager
11
11
  end
12
12
 
13
13
  def save_api_data(params)
14
- Thread.new do
15
14
  begin
16
15
  save_api_plans(params["plans"])
17
16
  rescue Exception => e
18
17
  Rails.logger.info "APP MANGAGER >>>> #{e.inspect}"
19
18
  end
20
- end
21
- Thread.new do
22
19
  begin
23
20
  save_api_charges(params["charges"])
24
21
  rescue Exception => e
25
22
  Rails.logger.info "APP MANGAGER >>>> #{e.inspect}"
26
23
  end
27
- end
28
- Thread.new do
29
24
  begin
30
25
  save_api_apps(params["apps"])
31
26
  rescue Exception => e
32
27
  Rails.logger.info "APP MANGAGER >>>> #{e.inspect}"
33
28
  end
34
- end
35
- Thread.new do
36
29
  begin
37
30
  save_api_app_structures(params["app_structures"])
38
31
  rescue Exception => e
39
32
  Rails.logger.info "APP MANGAGER >>>> #{e.inspect}"
40
33
  end
41
- end
42
- Thread.new do
43
34
  begin
44
35
  save_api_discount_plans(params["discount_plans"])
45
36
  rescue Exception => e
46
37
  Rails.logger.info "APP MANGAGER >>>> #{e.inspect}"
47
38
  end
48
- end
49
- Thread.new do
50
39
  begin
51
40
  save_api_extend_trials(params["extend_trials"])
52
41
  rescue Exception => e
53
42
  Rails.logger.info "APP MANGAGER >>>> #{e.inspect}"
54
43
  end
55
- end
44
+ begin
45
+ save_api_plan_users(params["plan_users"])
46
+ rescue Exception => e
47
+ Rails.logger.info "APP MANGAGER >>>> #{e.inspect}"
48
+ end
56
49
  end
57
50
 
58
51
  def save_api_plans(plans)
59
52
  @apm_db.execute("DROP TABLE IF EXISTS plans;")
60
- @apm_db.execute "CREATE TABLE IF NOT EXISTS plans(id integer,type varchar(255), name varchar(255), price float, offer_text varchar(255), interval text, shopify_plans text, trial_days integer, test boolean, on_install integer, is_custom boolean, app_id integer, base_plan integer, created_at datetime, updated_at datetime, public boolean, discount integer, cycle_count integer, store_base_plan boolean, discount_type varchar(255), affiliate text, features text)"
53
+ @apm_db.execute "CREATE TABLE IF NOT EXISTS plans(id integer,type varchar(255), name varchar(255), price float, offer_text varchar(255), interval text, shopify_plans text, trial_days integer, test boolean, on_install integer, is_custom boolean, app_id integer, base_plan integer, created_at datetime, updated_at datetime, public boolean, discount integer, cycle_count integer, store_base_plan boolean, discount_type varchar(255), affiliate text, features text, deleted_at datetime)"
61
54
 
62
55
  if plans.any?
63
56
  plans.each do |plan|
@@ -73,7 +66,7 @@ module AppManager
73
66
  is_custom = plan['is_custom'] ? 1 : 0
74
67
  public_val = plan['public'] ? 1 : 0
75
68
  store_base_plan = plan['store_base_plan'] ? 1 : 0
76
- @apm_db.execute("INSERT INTO plans ( id , type , name , price , offer_text , interval , shopify_plans , trial_days , test , on_install , is_custom , app_id , base_plan , created_at, updated_at , public , discount , cycle_count , store_base_plan , discount_type, affiliate, features ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",plan["id"], plan["type"], plan["name"], plan["price"], plan["offer_text"], "#{interval}", "#{shopify_plans}", plan["trial_days"], plan_test, plan["on_install"], is_custom, plan["app_id"], plan["base_plan"], plan["created_at"], plan["updated_at"],public_val, plan["discount"], plan["cycle_count"], store_base_plan, plan["discount_type"], "#{affiliate}", "#{features}")
69
+ @apm_db.execute("INSERT INTO plans ( id , type , name , price , offer_text , interval , shopify_plans , trial_days , test , on_install , is_custom , app_id , base_plan , created_at, updated_at , public , discount , cycle_count , store_base_plan , discount_type, affiliate, features, deleted_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",plan["id"], plan["type"], plan["name"], plan["price"], plan["offer_text"], "#{interval}", "#{shopify_plans}", plan["trial_days"], plan_test, plan["on_install"], is_custom, plan["app_id"], plan["base_plan"], plan["created_at"], plan["updated_at"],public_val, plan["discount"], plan["cycle_count"], store_base_plan, plan["discount_type"], "#{affiliate}", "#{features}",plan["deleted_at"])
77
70
  end
78
71
  end
79
72
  end
@@ -129,6 +122,16 @@ module AppManager
129
122
  end
130
123
  end
131
124
 
125
+ def save_api_plan_users(plan_users)
126
+ @apm_db.execute("DROP TABLE IF EXISTS plan_users;")
127
+ @apm_db.execute "CREATE TABLE IF NOT EXISTS plan_users(id integer,shop_domain varchar(255),plan_id integer,created_by integer,created_at datetime,updated_at datetime)"
128
+ if plan_users.any?
129
+ plan_users.each do |plan_user|
130
+ @apm_db.execute("INSERT INTO plan_users (id ,shop_domain, plan_id, created_by, created_at, updated_at ) VALUES (?,?,?,?,?,?)", plan_user['id'], plan_user['shop_domain'], plan_user['plan_id'], plan_user['created_by'], plan_user['created_at'], plan_user['updated_at'])
131
+ end
132
+ end
133
+ end
134
+
132
135
 
133
136
  def get_local_app_structures
134
137
  app_structures = {}
@@ -146,38 +149,89 @@ module AppManager
146
149
  end
147
150
 
148
151
 
149
- def get_local_plans
150
- plans = []
151
- @apm_db.execute( "SELECT * FROM plans;") do |plan|
152
- new_plan = {}
153
- plan.each_with_index do |(key, value), index|
154
- if ['interval'].include?(key)
155
- val = eval(value)
156
- new_plan[key] = val
157
- new_plan[key] = val['value'] if val rescue {}
158
- elsif ['shopify_plans'].include?(key)
159
- val = eval(value)
160
- new_plan[key] = val.collect{|e|e['value']}
161
- elsif ['affiliate'].include?(key)
162
- new_plan[key] = eval(value)
163
- elsif ['is_custom','public','store_base_plan'].include?(key)
164
- new_plan[key] = (value == 0 ? false : true)
165
- elsif ['test'].include?(key)
166
- new_plan[key] = (value == 0 ? nil : true)
167
- elsif ['features'].include?(key)
168
- value = eval(value)
169
- value = value.each {|e| e.delete("id")}.each {|e| e.delete("created_at")}.each {|e| e.delete("updated_at")}.group_by{|h| h['feature_id']}
170
- new_feature = {}
171
- value.each_with_index do |(k, v), index|
172
- new_feature[k] = v.first if v.class == Array
152
+ def get_local_plans(params)
153
+ plans_data = []
154
+
155
+ active_plan_id = nil
156
+ charges = @apm_db.execute( "SELECT * FROM charges WHERE shop_domain = ? ",params['shop_domain'])
157
+ active_plan_id = charges.first['plan_id'] if charges.any?
158
+
159
+ custom_plan_ids = []
160
+ plan_users = @apm_db.execute( "SELECT * FROM plan_users WHERE shop_domain = ? ",params['shop_domain'])
161
+ custom_plan_ids = plan_users.collect{|e|e['plan_id']} if plan_users.any?
162
+
163
+ custom_plan_base_ids = []
164
+ plan_data = @apm_db.execute( "SELECT * FROM plans WHERE id IN (?) AND base_plan IS NOT NULL;",custom_plan_ids)
165
+ custom_plan_base_ids = plan_data.collect{|e|e['base_plan']} if plan_data.any?
166
+
167
+ if active_plan_id && custom_plan_base_ids.include?(active_plan_id)
168
+ custom_plan_base_ids.delete(active_plan_id)
169
+ end
170
+
171
+ if custom_plan_base_ids.any?
172
+ plans = @apm_db.execute( "SELECT * FROM plans WHERE (public = ? OR id IN (?)) AND id NOT IN (?)", 1,custom_plan_ids,custom_plan_base_ids)
173
+ else
174
+ plans = @apm_db.execute( "SELECT * FROM plans WHERE (public = ? OR id IN (?))", 1,custom_plan_ids)
175
+ end
176
+
177
+ if plans.any?
178
+
179
+ plans.each do |plan|
180
+ new_plan = {}
181
+ plan.each_with_index do |(key, value), index|
182
+ if ['interval'].include?(key)
183
+ val = eval(value)
184
+ new_plan[key] = val
185
+ new_plan[key] = val['value'] if val rescue {}
186
+ elsif ['shopify_plans'].include?(key)
187
+ val = eval(value)
188
+ new_plan[key] = val.collect{|e|e['value']}
189
+ elsif ['affiliate'].include?(key)
190
+ new_plan[key] = eval(value)
191
+ elsif ['is_custom','public','store_base_plan'].include?(key)
192
+ new_plan[key] = (value == 0 ? false : true)
193
+ elsif ['test'].include?(key)
194
+ new_plan[key] = (value == 0 ? nil : true)
195
+ elsif ['features'].include?(key)
196
+ value = eval(value)
197
+ value = value.each {|e| e.delete("id")}.each {|e| e.delete("created_at")}.each {|e| e.delete("updated_at")}
198
+ new_plan[key] = value
199
+ else
200
+ new_plan[key] = value unless key.class == Integer
173
201
  end
174
- new_plan[key] = new_feature
202
+ end
203
+ plans_data.push(new_plan)
204
+ end
205
+
206
+ features_by_plans = plans_data.collect{|e|e['features']}
207
+ if features_by_plans.any? && AppManager.configuration.plan_features.any?
208
+ features_by_plans_data = []
209
+ features = AppManager.configuration.plan_features
210
+ features_by_plans.each do |features_by_plan|
211
+ features_by_plan.each do |fp|
212
+ fp['name'] = features.find{|e| e['uuid'] == fp['feature_id']}['name'] rescue nil
213
+ fp['format'] = features.find{|e| e['uuid'] == fp['feature_id']}['format'] rescue nil
214
+ features_by_plans_data.push(fp)
215
+ end
216
+ end
217
+ end
218
+
219
+ plans_data.each do |plan|
220
+ if features_by_plans_data.select{|e| e['plan_id'] == plan['id']}.size > 0
221
+ feature_hash = {}
222
+ features_by_plans_data.select{|e| e['plan_id'] == plan['id']}.each do |fp|
223
+ feature_hash[fp["feature_id"]] = fp
224
+ end
225
+ features = feature_hash
175
226
  else
176
- new_plan[key] = value unless key.class == Integer
227
+ features = nil
177
228
  end
229
+ plan['features'] = features
178
230
  end
179
- plans.push(new_plan)
180
- end
231
+
232
+ plans = plans_data
233
+ end
234
+
181
235
  return plans
182
236
  end
183
237
 
@@ -72,7 +72,7 @@ module AppManager
72
72
 
73
73
  discount_type = plan['discount_type'] || "percentage"
74
74
  discount_val = discount_type == "percentage" ? (plan['discount'].to_f/ 100) : "#{plan['discount']}"
75
- plan_discount = plan['discount'] ? { "discount" => { "durationLimitInIntervals" => (plan['cycle_count'] || nil), "value" => {"#{discount_type}" => discount_val} } } : {}
75
+ plan_discount = plan['discount'] ? { "discount" => { "durationLimitInIntervals" => (plan['cycle_count'].to_i || 0), "value" => {"#{discount_type}" => discount_val} } } : {}
76
76
 
77
77
  price_details = {
78
78
  "price": { "amount": plan['price'], "currencyCode": 'USD' },
@@ -7,8 +7,11 @@ module AppManager
7
7
  def has_plan
8
8
  if !self[AppManager.configuration.plan_id_or_name_field]
9
9
  return false;
10
+ end
11
+ if self[AppManager.configuration.field_names['grandfathered']]
12
+ return true;
10
13
  end
11
- plan_id = self.plan_id
14
+ plan_id = self[AppManager.configuration.plan_id_or_name_field]
12
15
  if !plan_id
13
16
  Rails.logger.info "Plan id found nil or not set"
14
17
  return false;
@@ -26,9 +29,9 @@ module AppManager
26
29
 
27
30
 
28
31
  def plan_features
29
- plan_id = self.plan_id
32
+ plan_id = self[AppManager.configuration.plan_id_or_name_field]
30
33
  if !plan_id
31
- raise "Plan id not found"
34
+ raise Error, "Plan id not found"
32
35
  end
33
36
  plan_obj = AppManager::Client.new
34
37
  plans = plan_obj.get_plan(plan_id)
@@ -70,6 +73,27 @@ module AppManager
70
73
  shop_domain ? plan_obj.get_remaining_days(shop_domain,trial_activated_at_val,plan_id) : 0
71
74
  end
72
75
 
76
+
77
+ def get_plan
78
+ if !self[AppManager.configuration.plan_id_or_name_field]
79
+ raise Error, "Invalid params, must have charge_id,shop && plan"
80
+ end
81
+ plan_obj = AppManager::Client.new
82
+ return plan_obj.get_plan(self[AppManager.configuration.plan_id_or_name_field])
83
+ end
84
+
85
+ def get_charge
86
+ begin
87
+ shop_domain = self[AppManager.configuration.shopify_domain_field]
88
+ plan_obj = AppManager::Client.new
89
+ return plan_obj.get_charge(self[AppManager.configuration.shopify_domain_field])
90
+ rescue Exception => e
91
+ return "#{e.inspect}"
92
+ end
93
+ end
94
+
95
+
96
+
73
97
  private
74
98
 
75
99
  def casted_value(value,value_type)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppManager
4
- VERSION = "1.1.0"
4
+ VERSION = "1.1.1"
5
5
  end
data/lib/app_manager.rb CHANGED
@@ -15,6 +15,7 @@ require "app_manager/protection"
15
15
  require "app_manager/model"
16
16
  require "app_manager/fail_safe"
17
17
  require 'app_manager/railtie' if defined?(Rails)
18
+ require 'app_manager/exceptions'
18
19
 
19
20
  module AppManager
20
21
  def self.configure
@@ -1,7 +1,10 @@
1
1
  require "rails/generators/base"
2
+ require "rails/generators/active_record"
3
+
2
4
  module AppManager
3
5
  module Generators
4
6
  class InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
5
8
  source_root File.expand_path('../templates', __FILE__)
6
9
 
7
10
  def mount_engine
@@ -16,6 +19,25 @@ module AppManager
16
19
  template("app_manager.rb", "config/initializers/app_manager.rb")
17
20
  end
18
21
 
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
25
+
26
+ private
27
+
28
+ def rails_migration_version
29
+ Rails.version.match(/\d\.\d/)[0]
30
+ end
31
+
32
+ class << self
33
+ private :next_migration_number
34
+
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
40
+
19
41
  end
20
42
  end
21
43
  end
@@ -0,0 +1,7 @@
1
+ class AddPlanTrialGrandfatheredToShops < ActiveRecord::Migration[<%= rails_migration_version %>]
2
+ def change
3
+ add_column :shops, :plan_id, :bigint unless column_exists? :shops, :plan_id
4
+ add_column :shops, :trial_activated_at, :datetime unless column_exists? :shops, :trial_activated_at
5
+ add_column :shops, :grandfathered, :boolean unless column_exists? :shops, :grandfathered
6
+ end
7
+ end
@@ -11,10 +11,11 @@ AppManager.configure do |config|
11
11
  'name' => 'shopify_domain', # demo-rahul-tiwari.myshopify.com
12
12
  'shopify_email' => 'email', # rahul.t@hulkapps.com
13
13
  'shopify_token' => 'shopify_token',
14
- 'shopify_plan' => 'plan_name', # partner_test
14
+ 'shopify_plan' => 'shopify_plan', # partner_test
15
15
  'plan_id' => 'plan_id', # 1. t
16
16
  'created_at' => 'created_at', # 2022-04-15 10:43:05
17
- 'trial_activated_at' => 'trial_activated_at' # field name that stores trial start/activated date
17
+ 'trial_activated_at' => 'trial_activated_at', # field name that stores trial start/activated date
18
+ 'grandfathered' => 'grandfathered'
18
19
  }
19
20
  config.plan_features = [
20
21
  {
@@ -24,7 +25,10 @@ AppManager.configure do |config|
24
25
  "description" => "Feature Description",
25
26
  "value_type" => "integer",
26
27
  "format" => "count",
27
- "display_order" => 1
28
+ "display_order" => 1,
29
+ "hidden_feature" => false,
30
+ "group_order" => "1",
31
+ "group" => "Group Name",
28
32
  },
29
33
  {
30
34
  "uuid" => "9f18f95a-bfaf-11ec-9d64-0242ac120002",
@@ -33,7 +37,10 @@ AppManager.configure do |config|
33
37
  "description" => "Feature Description",
34
38
  "value_type" => "boolean",
35
39
  "format" => "percentage",
36
- "display_order" => 2
40
+ "display_order" => 2,
41
+ "hidden_feature" => false,
42
+ "group_order" => "1",
43
+ "group" => "Group Name",
37
44
  },
38
45
  {
39
46
  "uuid" => "9f190a26-bfaf-11ec-9d64-0242ac120002",
@@ -42,7 +49,10 @@ AppManager.configure do |config|
42
49
  "description" => "Feature Description",
43
50
  "value_type" => "string",
44
51
  "format" => "string",
45
- "display_order" => 3
52
+ "display_order" => 3,
53
+ "hidden_feature" => false,
54
+ "group_order" => "1",
55
+ "group" => "Group Name",
46
56
  },
47
57
  {
48
58
  "uuid" => "9f191340-bfaf-11ec-9d64-0242ac12000",
@@ -55,7 +65,23 @@ AppManager.configure do |config|
55
65
  "val 2"
56
66
  ],
57
67
  "format" => "string",
58
- "display_order" => 4
68
+ "display_order" => 4,
69
+ "hidden_feature" => false,
70
+ "group_order" => "1",
71
+ "group" => "Group Name",
59
72
  }
60
- ] #Required, Values type : integer, boolean, string, array
61
- end
73
+ ]
74
+ end
75
+ #Required, Values type : integer, boolean, string, array #
76
+ #Format: percentage, count, string
77
+
78
+
79
+ #################################################
80
+ # Following method receives payload after charge created functionality. Use this for 'MauticCall'
81
+ # payload contains plan, charge and previous_charge
82
+
83
+ ActiveSupport::Notifications.subscribe "charge_created" do |name, start, finish, id, payload|
84
+ Rails.logger.debug "========APP MANAGER========="
85
+ Rails.logger.debug "DATA : #{payload}"
86
+ Rails.logger.debug "========APP MANAGER========="
87
+ 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.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hulkapps
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-01 00:00:00.000000000 Z
11
+ date: 2022-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -85,6 +85,7 @@ files:
85
85
  - app/controllers/app_manager/charges_controller.rb
86
86
  - app/controllers/app_manager/plans_controller.rb
87
87
  - app/controllers/concerns/app_manager/authenticate.rb
88
+ - app/services/app_manager/event_handler.rb
88
89
  - app_manager-0.1.0.gem
89
90
  - app_manager.gemspec
90
91
  - bin/console
@@ -99,6 +100,7 @@ files:
99
100
  - lib/app_manager/client/plans.rb
100
101
  - lib/app_manager/config.rb
101
102
  - lib/app_manager/engine.rb
103
+ - lib/app_manager/exceptions.rb
102
104
  - lib/app_manager/fail_safe.rb
103
105
  - lib/app_manager/graphql_helper.rb
104
106
  - lib/app_manager/model.rb
@@ -108,6 +110,7 @@ files:
108
110
  - lib/app_manager/tasks/sync/local_app_manager.rake
109
111
  - lib/app_manager/version.rb
110
112
  - lib/generators/app_manager/install/install_generator.rb
113
+ - lib/generators/app_manager/install/templates/add_plan_trial_grandfathered_to_shops.erb
111
114
  - lib/generators/app_manager/install/templates/app_manager.rb.tt
112
115
  homepage: https://www.hulkapps.com
113
116
  licenses: []