paid_up 0.9.13 → 0.9.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +20 -0
- data/Gemfile +5 -1
- data/Rakefile +12 -10
- data/VERSION +1 -1
- data/app/controllers/paid_up/paid_up_controller.rb +8 -3
- data/app/controllers/paid_up/plans_controller.rb +2 -1
- data/app/controllers/paid_up/subscriptions_controller.rb +19 -6
- data/app/helpers/paid_up/features_helper.rb +19 -6
- data/app/helpers/paid_up/paid_up_helper.rb +6 -3
- data/app/helpers/paid_up/plans_helper.rb +12 -5
- data/app/helpers/paid_up/subscriptions_helper.rb +10 -3
- data/app/models/paid_up/ability.rb +43 -44
- data/app/models/paid_up/plan.rb +81 -69
- data/app/models/paid_up/plan_feature_setting.rb +17 -9
- data/app/models/paid_up/unlimited.rb +15 -13
- data/app/views/devise/confirmations/new.html.haml +1 -1
- data/app/views/devise/passwords/edit.html.haml +1 -1
- data/app/views/devise/passwords/new.html.haml +1 -1
- data/app/views/devise/registrations/_new_form.html.haml +1 -1
- data/app/views/devise/registrations/new.html.haml +1 -1
- data/app/views/devise/sessions/new.html.haml +1 -1
- data/app/views/devise/unlocks/new.html.haml +1 -1
- data/app/views/layouts/mailer.html.haml +1 -1
- data/app/views/layouts/mailer.text.haml +1 -1
- data/app/views/paid_up/features/_abilities_table.html.haml +1 -1
- data/app/views/paid_up/plans/index.html.haml +1 -1
- data/app/views/paid_up/subscriptions/new.html.haml +1 -1
- data/config/initializers/stripe.rb +3 -3
- data/coverage/.last_run.json +1 -1
- data/coverage/.resultset.json +414 -253
- data/db/migrate/20150407110101_create_paid_up_plans_table.rb +3 -3
- data/lib/generators/paid_up/install/install_generator.rb +42 -33
- data/lib/generators/paid_up/install/templates/ability.rb +1 -0
- data/lib/generators/paid_up/install/templates/initializer.rb +16 -14
- data/lib/generators/paid_up/utils.rb +11 -4
- data/lib/paid_up/configuration.rb +13 -8
- data/lib/paid_up/engine.rb +4 -3
- data/lib/paid_up/extensions/integer.rb +8 -5
- data/lib/paid_up/extensions/stripe.rb +10 -9
- data/lib/paid_up/feature.rb +27 -17
- data/lib/paid_up/localization.rb +17 -18
- data/lib/paid_up/mixins/paid_for.rb +66 -54
- data/lib/paid_up/mixins/subscriber.rb +154 -161
- data/lib/paid_up/railtie.rb +1 -1
- data/lib/paid_up/validators/rolify_rows.rb +14 -6
- data/lib/paid_up/validators/table_rows.rb +14 -6
- data/lib/paid_up/version.rb +1 -1
- data/lib/paid_up.rb +7 -8
- data/paid_up.gemspec +21 -8
- data/spec/controllers/paid_up/plans_spec.rb +6 -6
- data/spec/controllers/paid_up/subscriptions_spec.rb +68 -68
- data/spec/dummy/Rakefile +2 -1
- data/spec/dummy/app/assets/stylesheets/application.css.scss +3 -16
- data/spec/dummy/app/controllers/application_controller.rb +1 -1
- data/spec/dummy/app/models/doodad.rb +1 -1
- data/spec/dummy/app/models/group.rb +1 -1
- data/spec/dummy/app/models/role.rb +4 -4
- data/spec/dummy/app/models/user.rb +1 -1
- data/spec/dummy/app/views/layouts/application.html.haml +2 -2
- data/spec/dummy/app/views/pages/index.html.haml +1 -1
- data/spec/dummy/config/application.rb +16 -12
- data/spec/dummy/config/environments/development.rb +4 -3
- data/spec/dummy/config/environments/production.rb +10 -6
- data/spec/dummy/config/environments/test.rb +3 -2
- data/spec/dummy/config/initializers/assets.rb +2 -1
- data/spec/dummy/config/initializers/backtrace_silencers.rb +4 -2
- data/spec/dummy/config/initializers/devise.rb +58 -42
- data/spec/dummy/config/initializers/high_voltage.rb +1 -1
- data/spec/dummy/config/initializers/mime_types.rb +1 -1
- data/spec/dummy/config/initializers/paid_up.rb +16 -14
- data/spec/dummy/config/initializers/rolify.rb +3 -2
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -1
- data/spec/dummy/config/routes.rb +2 -2
- data/spec/dummy/db/migrate/20150523010827_add_devise_to_users.rb +2 -2
- data/spec/dummy/db/migrate/20150523010837_rolify_create_roles.rb +2 -2
- data/spec/dummy/db/migrate/20160207184112_create_paid_up_plans_table.paid_up.rb +3 -3
- data/spec/dummy/db/schema.rb +53 -53
- data/spec/dummy/db/seeds.rb +41 -56
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/tasks/system.rake +2 -2
- data/spec/factories/group.rb +1 -1
- data/spec/factories/plan.rb +1 -1
- data/spec/factories/plan_feature_setting.rb +1 -1
- data/spec/factories/user.rb +13 -11
- data/spec/models/group_spec.rb +8 -7
- data/spec/models/paid_up/feature_spec.rb +18 -4
- data/spec/models/paid_up/plan_feature_setting_spec.rb +2 -2
- data/spec/models/paid_up/plan_spec.rb +12 -8
- data/spec/models/user_spec.rb +88 -78
- data/spec/paid_up_spec.rb +1 -1
- data/spec/rails_helper.rb +5 -5
- data/spec/routing/paid_up/plans_spec.rb +3 -3
- data/spec/routing/paid_up/subscription_spec.rb +30 -7
- data/spec/spec_helper.rb +7 -52
- data/spec/support/controller_macros.rb +2 -2
- data/spec/support/factory_girl.rb +1 -1
- data/spec/support/{features.rb → loaded_site/features.rb} +2 -2
- data/spec/support/{groups.rb → loaded_site/groups.rb} +1 -1
- data/spec/support/{loaded_site.rb → loaded_site/loaded_site.rb} +1 -1
- data/spec/support/{plans.rb → loaded_site/plans.rb} +8 -4
- data/spec/support/{users.rb → loaded_site/users.rb} +1 -1
- data/spec/support/stripe.rb +10 -13
- data/spec/views/paid_up/plans_spec.rb +17 -17
- data/spec/views/paid_up/subscriptions_spec.rb +24 -14
- metadata +64 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bf978e51d7d4fdba2c09b1410722a56342e63af
|
4
|
+
data.tar.gz: 0164070ba66ee76293a1f7fefa579170671775e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a07f651feba3290f6d59ee81d8585ced8afba55f117fe05b543e87a2d5d72445a5ef59b705b8f80988c1cc4e2e1cbdc7090d0c1e15ac4cda2513c1380c167a57
|
7
|
+
data.tar.gz: 8c4a8e15bc2a6daed2cf286b2dfb705d059efeae6d1c0ac389fa4bfa3cd14ed00515922fc6fe735484b25345b744addfef7579f859c486b2b10c7b67357e5540
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- paid_up.gemspec
|
4
|
+
- db/migrate/*
|
5
|
+
- spec/dummy/db/schema.rb
|
6
|
+
- spec/dummy/db/migrate/*
|
7
|
+
Style/ClassVars:
|
8
|
+
Enabled: false
|
9
|
+
Metrics/AbcSize:
|
10
|
+
Enabled: false
|
11
|
+
Metrics/ClassLength:
|
12
|
+
Enabled: false
|
13
|
+
Metrics/CyclomaticComplexity:
|
14
|
+
Enabled: false
|
15
|
+
Metrics/MethodLength:
|
16
|
+
Enabled: false
|
17
|
+
Metrics/ModuleLength:
|
18
|
+
Enabled: false
|
19
|
+
Metrics/PerceivedComplexity:
|
20
|
+
Enabled: false
|
data/Gemfile
CHANGED
@@ -20,6 +20,10 @@ group :development do
|
|
20
20
|
gem 'jeweler', '~> 2'
|
21
21
|
gem 'bundler', '~> 1'
|
22
22
|
gem 'web-console', '~> 3.0'
|
23
|
+
gem 'pre-commit', '~> 0.27'
|
24
|
+
gem 'rubocop', '~> 0.37'
|
25
|
+
gem 'coffeelint', '~> 1.14'
|
26
|
+
gem 'scss_lint', '~> 0.47.0', require: false
|
23
27
|
end
|
24
28
|
|
25
29
|
group :test, :development do
|
@@ -39,4 +43,4 @@ group :test do
|
|
39
43
|
gem 'shoulda-matchers', '~> 2.8'
|
40
44
|
gem 'launchy', '~> 2.4', require: false
|
41
45
|
gem 'coveralls', '~> 0.8', require: false
|
42
|
-
end
|
46
|
+
end
|
data/Rakefile
CHANGED
@@ -6,14 +6,17 @@ end
|
|
6
6
|
|
7
7
|
require 'jeweler'
|
8
8
|
Jeweler::Tasks.new do |gem|
|
9
|
-
# gem is a Gem::Specification...
|
10
|
-
|
11
|
-
gem.
|
12
|
-
gem.
|
13
|
-
gem.
|
14
|
-
gem.
|
15
|
-
|
16
|
-
gem.
|
9
|
+
# gem is a Gem::Specification...
|
10
|
+
# see http://docs.rubygems.org/read/chapter/20 for more options
|
11
|
+
gem.name = 'paid_up'
|
12
|
+
gem.homepage = 'http://www.gemvein.com/museum/cases/paid_up'
|
13
|
+
gem.license = 'MIT'
|
14
|
+
gem.summary = 'Allows a model of your choosing to subscribe to a plan, which'\
|
15
|
+
' enables features.'
|
16
|
+
gem.description = 'Allows a model of your choosing (such as users) to '\
|
17
|
+
'subscribe to a plan, which enables features.'
|
18
|
+
gem.email = 'karen.e.lundgren@gmail.com'
|
19
|
+
gem.authors = ['Karen Lundgren']
|
17
20
|
# dependencies defined in Gemfile
|
18
21
|
end
|
19
22
|
Jeweler::RubygemsDotOrgTasks.new
|
@@ -24,5 +27,4 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
24
27
|
spec.pattern = FileList['spec/**/*_spec.rb']
|
25
28
|
end
|
26
29
|
|
27
|
-
task :
|
28
|
-
|
30
|
+
task default: :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.14
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module PaidUp
|
2
|
+
# PaidUp Controller
|
2
3
|
class PaidUpController < ApplicationController
|
3
4
|
helper :all
|
4
5
|
|
5
6
|
before_action :set_locale
|
6
7
|
before_filter :warn_if_delinquent
|
7
8
|
|
8
|
-
|
9
|
+
private
|
10
|
+
|
9
11
|
def set_locale
|
10
12
|
I18n.locale = params[:locale] || I18n.default_locale
|
11
13
|
end
|
@@ -13,9 +15,12 @@ module PaidUp
|
|
13
15
|
def warn_if_delinquent
|
14
16
|
if user_signed_in? && params[:controller] != 'paid_up/subscriptions'
|
15
17
|
if current_user.plan.nil? || current_user.stripe_data.delinquent
|
16
|
-
flash[:error] = :account_is_delinquent.l +
|
18
|
+
flash[:error] = :account_is_delinquent.l +
|
19
|
+
:to_disable_this_message_subscribe.l(
|
20
|
+
subscribe_link: paid_up.plans_path
|
21
|
+
)
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
21
|
-
end
|
26
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module PaidUp
|
2
|
+
# Subscriptions Controller
|
2
3
|
class SubscriptionsController < PaidUpController
|
3
4
|
before_filter :authenticate_user!
|
4
5
|
before_filter :set_plan, only: [:new, :create]
|
@@ -9,18 +10,29 @@ module PaidUp
|
|
9
10
|
|
10
11
|
def new
|
11
12
|
# nothing to do, @plan set by #set_plan
|
12
|
-
|
13
|
-
create
|
14
|
-
end
|
13
|
+
(current_user.can_downgrade_to?(@plan) || @plan.amount == 0) && create
|
15
14
|
end
|
16
15
|
|
17
16
|
def create
|
18
17
|
# @plan set by #set_plan
|
19
18
|
current_user.update_attribute(:coupon_code, params[:coupon_code])
|
20
19
|
if current_user.subscribe_to_plan(@plan, params[:stripeToken])
|
21
|
-
redirect_to
|
20
|
+
redirect_to(
|
21
|
+
subscriptions_path,
|
22
|
+
flash: {
|
23
|
+
notice: :you_are_now_subscribed_to_the_plan.l(
|
24
|
+
plan_name: current_user.plan.title
|
25
|
+
)
|
26
|
+
}
|
27
|
+
)
|
22
28
|
else
|
23
|
-
redirect_to
|
29
|
+
redirect_to(
|
30
|
+
new_plan_subscription_path(@plan),
|
31
|
+
flash: {
|
32
|
+
error: current_user.errors.full_messages ||
|
33
|
+
:could_not_subscribe_to_plan.l(plan: @plan.title)
|
34
|
+
}
|
35
|
+
)
|
24
36
|
end
|
25
37
|
rescue Stripe::InvalidRequestError => e
|
26
38
|
flash[:error] = e.message
|
@@ -31,8 +43,9 @@ module PaidUp
|
|
31
43
|
end
|
32
44
|
|
33
45
|
private
|
46
|
+
|
34
47
|
def set_plan
|
35
48
|
@plan = PaidUp::Plan.find(params[:plan_id])
|
36
49
|
end
|
37
50
|
end
|
38
|
-
end
|
51
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module PaidUp
|
2
|
+
# PaidUp Features Helper
|
2
3
|
module FeaturesHelper
|
3
4
|
include PaidUp::PaidUpHelper
|
4
5
|
|
@@ -6,7 +7,7 @@ module PaidUp
|
|
6
7
|
data = {}
|
7
8
|
features = PaidUp::Feature.all
|
8
9
|
|
9
|
-
|
10
|
+
features.each do |feature|
|
10
11
|
data[feature.title] = feature_display feature, plan
|
11
12
|
end
|
12
13
|
|
@@ -39,11 +40,11 @@ module PaidUp
|
|
39
40
|
|
40
41
|
plans = PaidUp::Plan.subscribable
|
41
42
|
if options[:only].present?
|
42
|
-
plans = plans.where(
|
43
|
+
plans = plans.where(id: options[:only])
|
43
44
|
options.delete(:only)
|
44
45
|
end
|
45
46
|
if options[:except].present?
|
46
|
-
plans = plans.where(
|
47
|
+
plans = plans.where.not(id: options[:except])
|
47
48
|
options.delete(:except)
|
48
49
|
end
|
49
50
|
|
@@ -54,12 +55,24 @@ module PaidUp
|
|
54
55
|
highlight_plan = nil
|
55
56
|
end
|
56
57
|
|
57
|
-
render(
|
58
|
+
render(
|
59
|
+
partial: 'paid_up/features/table',
|
60
|
+
locals: {
|
61
|
+
should_add_buttons: should_add_buttons,
|
62
|
+
plans: plans,
|
63
|
+
features: features,
|
64
|
+
highlight_plan: highlight_plan,
|
65
|
+
html_options: options
|
66
|
+
}
|
67
|
+
)
|
58
68
|
end
|
59
69
|
|
60
70
|
def feature_abilities_table(options = {})
|
61
71
|
features = PaidUp::Feature.all
|
62
|
-
render(
|
72
|
+
render(
|
73
|
+
partial: 'paid_up/features/abilities_table',
|
74
|
+
locals: { features: features, html_options: options }
|
75
|
+
)
|
63
76
|
end
|
64
77
|
end
|
65
|
-
end
|
78
|
+
end
|
@@ -1,14 +1,17 @@
|
|
1
1
|
module PaidUp
|
2
|
+
# PaidUp PaidUp Helper
|
2
3
|
module PaidUpHelper
|
3
4
|
def date_range(start_date, end_date)
|
4
5
|
dates = []
|
5
|
-
if start_date.present? &&
|
6
|
+
if start_date.present? &&
|
7
|
+
(start_date.is_a?(Date) || start_date.is_a?(Integer))
|
6
8
|
dates << start_date.to_date
|
7
9
|
end
|
8
|
-
if end_date.present? &&
|
10
|
+
if end_date.present? &&
|
11
|
+
(end_date.is_a?(Date) || end_date.is_a?(Integer))
|
9
12
|
dates << end_date.to_date
|
10
13
|
end
|
11
14
|
dates.join('—').html_safe
|
12
15
|
end
|
13
16
|
end
|
14
|
-
end
|
17
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module PaidUp
|
2
|
+
# PaidUp Plans Helper
|
2
3
|
module PlansHelper
|
3
4
|
include ::ActionView::Helpers::NumberHelper
|
4
5
|
|
5
6
|
def plan_charge_human(plan, discount)
|
6
|
-
if !discount.nil?
|
7
|
+
if !discount.nil? && !discount.coupon.nil? && plan.amount != 0
|
7
8
|
orig_amount = plan.amount
|
8
9
|
amount = orig_amount
|
9
10
|
amount -= (discount.coupon.percent_off || 0) * 0.01 * amount
|
@@ -13,9 +14,16 @@ module PaidUp
|
|
13
14
|
orig_money = Money.new(orig_amount, plan.currency)
|
14
15
|
money = Money.new(amount, plan.currency)
|
15
16
|
|
16
|
-
html = content_tag
|
17
|
+
html = content_tag(
|
18
|
+
:s,
|
19
|
+
(orig_money.format + '/' + plan_period_phrase(plan))
|
20
|
+
)
|
17
21
|
html << ' '
|
18
|
-
html << content_tag(
|
22
|
+
html << content_tag(
|
23
|
+
:span,
|
24
|
+
(money.format + '/' + plan_period_phrase(plan)),
|
25
|
+
class: 'text-danger'
|
26
|
+
)
|
19
27
|
else
|
20
28
|
html = plan.money.format + '/' + plan_period_phrase(plan)
|
21
29
|
end
|
@@ -67,6 +75,5 @@ module PaidUp
|
|
67
75
|
html_options[:disabled] ||= disabled_state
|
68
76
|
icon_button_to css_class, icon_class, text, link, html_options
|
69
77
|
end
|
70
|
-
|
71
78
|
end
|
72
|
-
end
|
79
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module PaidUp
|
2
|
+
# PaidUp Subscriptions Helper
|
2
3
|
module SubscriptionsHelper
|
3
4
|
include PaidUp::PaidUpHelper
|
4
5
|
|
@@ -8,14 +9,20 @@ module PaidUp
|
|
8
9
|
data[:status.l] = subscription.status
|
9
10
|
|
10
11
|
if subscription.current_period_start || subscription.current_period_end
|
11
|
-
data[:paid_thru.l]= date_range(
|
12
|
+
data[:paid_thru.l] = date_range(
|
13
|
+
subscription.current_period_start,
|
14
|
+
subscription.current_period_end
|
15
|
+
)
|
12
16
|
end
|
13
17
|
|
14
18
|
if subscription.trial_start || subscription.trial_end
|
15
|
-
data[:trial_period.l]= date_range(
|
19
|
+
data[:trial_period.l] = date_range(
|
20
|
+
subscription.trial_start,
|
21
|
+
subscription.trial_end
|
22
|
+
)
|
16
23
|
end
|
17
24
|
|
18
25
|
dl data
|
19
26
|
end
|
20
27
|
end
|
21
|
-
end
|
28
|
+
end
|
@@ -1,55 +1,54 @@
|
|
1
1
|
module PaidUp
|
2
|
+
# PaidUp Ability model
|
2
3
|
module Ability
|
3
4
|
include CanCan::Ability
|
4
5
|
|
5
6
|
def initialize_paid_up(user)
|
6
7
|
features = PaidUp::Feature.all
|
7
|
-
|
8
|
+
features.each do |feature|
|
8
9
|
case feature.setting_type
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
else
|
20
|
-
cannot :create, feature.feature_model
|
21
|
-
end
|
22
|
-
else
|
23
|
-
cannot :delete, feature.feature_model
|
24
|
-
cannot :update, feature.feature_model
|
25
|
-
cannot :own, feature.feature_model
|
26
|
-
cannot :create, feature.feature_model
|
27
|
-
end
|
28
|
-
when 'rolify_rows'
|
29
|
-
can :index, feature.feature_model
|
30
|
-
can :show, feature.feature_model do |item|
|
31
|
-
item.enabled
|
32
|
-
end
|
33
|
-
if user.rolify_rows_allowed(feature.slug) > 0 || user.rolify_rows_unlimited?(feature.slug)
|
34
|
-
can :manage, feature.feature_model, id: feature.feature_model.with_role(:owner, user).pluck(:id)
|
35
|
-
can :own, feature.feature_model
|
36
|
-
if user.rolify_rows_remaining(feature.slug) > 0
|
37
|
-
can [:create, :new], feature.feature_model
|
38
|
-
else
|
39
|
-
cannot :create, feature.feature_model
|
40
|
-
end
|
41
|
-
else
|
42
|
-
cannot :delete, feature.feature_model
|
43
|
-
cannot :update, feature.feature_model
|
44
|
-
cannot :own, feature.feature_model
|
45
|
-
cannot :create, feature.feature_model
|
46
|
-
end
|
47
|
-
when 'boolean'
|
48
|
-
if user.plan.feature_setting feature.slug
|
49
|
-
can :use, feature.slug.to_sym
|
50
|
-
end
|
10
|
+
when 'table_rows'
|
11
|
+
can :index, feature.feature_model
|
12
|
+
can :show, feature.feature_model, &:enabled
|
13
|
+
if user.table_rows_allowed(feature.slug) > 0 ||
|
14
|
+
user.table_rows_unlimited?(feature.slug)
|
15
|
+
can :manage, feature.feature_model, user: user
|
16
|
+
can :own, feature.feature_model
|
17
|
+
cannot :create, feature.feature_model
|
18
|
+
user.table_rows_remaining(feature.slug) > 0 &&
|
19
|
+
can([:create, :new], feature.feature_model)
|
51
20
|
else
|
52
|
-
|
21
|
+
cannot :delete, feature.feature_model
|
22
|
+
cannot :update, feature.feature_model
|
23
|
+
cannot :own, feature.feature_model
|
24
|
+
cannot :create, feature.feature_model
|
25
|
+
end
|
26
|
+
when 'rolify_rows'
|
27
|
+
can :index, feature.feature_model
|
28
|
+
can :show, feature.feature_model, &:enabled
|
29
|
+
if user.rolify_rows_allowed(feature.slug) > 0 ||
|
30
|
+
user.rolify_rows_unlimited?(feature.slug)
|
31
|
+
can(
|
32
|
+
:manage,
|
33
|
+
feature.feature_model,
|
34
|
+
id: feature.feature_model.with_role(:owner, user).ids
|
35
|
+
)
|
36
|
+
can :own, feature.feature_model
|
37
|
+
cannot :create, feature.feature_model
|
38
|
+
user.rolify_rows_remaining(feature.slug) > 0 &&
|
39
|
+
can([:create, :new], feature.feature_model)
|
40
|
+
else
|
41
|
+
cannot :delete, feature.feature_model
|
42
|
+
cannot :update, feature.feature_model
|
43
|
+
cannot :own, feature.feature_model
|
44
|
+
cannot :create, feature.feature_model
|
45
|
+
end
|
46
|
+
when 'boolean'
|
47
|
+
if user.plan.feature_setting feature.slug
|
48
|
+
can :use, feature.slug.to_sym
|
49
|
+
end
|
50
|
+
else
|
51
|
+
raise(:unknown_feature_type.l)
|
53
52
|
end
|
54
53
|
end
|
55
54
|
end
|
data/app/models/paid_up/plan.rb
CHANGED
@@ -1,29 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
1
|
+
module PaidUp
|
2
|
+
# PaidUp Plan model
|
3
|
+
class Plan < ActiveRecord::Base
|
4
|
+
has_many(
|
5
|
+
:plan_feature_settings,
|
6
|
+
class_name: 'PaidUp::PlanFeatureSetting',
|
7
|
+
foreign_key: 'paid_up_plan_id',
|
8
|
+
inverse_of: :plan
|
9
|
+
)
|
10
|
+
accepts_nested_attributes_for :plan_feature_settings
|
11
|
+
|
12
|
+
after_initialize :load_stripe_data
|
13
|
+
after_save :expire_stripe_data
|
14
|
+
|
15
|
+
attr_accessor :stripe_data
|
16
|
+
|
17
|
+
validates_presence_of :title, :stripe_id
|
18
|
+
validates_uniqueness_of :title
|
19
|
+
|
20
|
+
default_scope { order('sort_order ASC') }
|
21
|
+
scope :subscribable, -> { where('sort_order >= ?', 0) }
|
22
|
+
scope :free, (lambda do
|
23
|
+
find_by_stripe_id(PaidUp.configuration.free_plan_stripe_id)
|
24
|
+
end)
|
25
|
+
|
26
|
+
def reload(*args, &blk)
|
27
|
+
super(*args, &blk)
|
28
|
+
load_stripe_data
|
29
|
+
self
|
30
|
+
end
|
22
31
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
32
|
+
def feature_setting(feature_name)
|
33
|
+
feature = PaidUp::Feature.find_by_slug(feature_name) ||
|
34
|
+
raise(:feature_not_found.l)
|
35
|
+
raw = plan_feature_settings.where(feature: feature_name)
|
36
|
+
case feature.setting_type
|
27
37
|
when 'boolean'
|
28
38
|
if raw.empty?
|
29
39
|
false
|
@@ -38,65 +48,67 @@ class PaidUp::Plan < ActiveRecord::Base
|
|
38
48
|
end
|
39
49
|
else
|
40
50
|
raise :error_handling_feature_setting.l feature: feature
|
51
|
+
end
|
41
52
|
end
|
42
|
-
end
|
43
53
|
|
44
|
-
|
45
|
-
|
46
|
-
|
54
|
+
def feature_unlimited?(feature_name)
|
55
|
+
feature_setting(feature_name) == PaidUp::Unlimited.to_i
|
56
|
+
end
|
47
57
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
58
|
+
def interval
|
59
|
+
if stripe_data.present?
|
60
|
+
stripe_data.interval
|
61
|
+
else
|
62
|
+
:default_interval.l
|
63
|
+
end
|
53
64
|
end
|
54
|
-
end
|
55
65
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
66
|
+
def interval_count
|
67
|
+
if stripe_data.present?
|
68
|
+
stripe_data.interval_count
|
69
|
+
else
|
70
|
+
1
|
71
|
+
end
|
61
72
|
end
|
62
|
-
end
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
74
|
+
def amount
|
75
|
+
if stripe_data.present?
|
76
|
+
stripe_data.amount
|
77
|
+
else
|
78
|
+
0
|
79
|
+
end
|
69
80
|
end
|
70
|
-
end
|
71
81
|
|
72
|
-
|
73
|
-
|
74
|
-
|
82
|
+
def money
|
83
|
+
Money.new(amount, currency)
|
84
|
+
end
|
75
85
|
|
76
|
-
|
77
|
-
|
78
|
-
|
86
|
+
def charge
|
87
|
+
money.amount
|
88
|
+
end
|
79
89
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
90
|
+
def currency
|
91
|
+
if stripe_data.present?
|
92
|
+
stripe_data.currency.upcase
|
93
|
+
else
|
94
|
+
:default_currency.l.upcase
|
95
|
+
end
|
85
96
|
end
|
86
|
-
end
|
87
97
|
|
88
|
-
|
98
|
+
private
|
89
99
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
100
|
+
def load_stripe_data
|
101
|
+
if stripe_id.present?
|
102
|
+
self.stripe_data = Rails.cache.fetch(
|
103
|
+
"#{stripe_id}/stripe_data", expires_in: 12.hours
|
104
|
+
) do
|
105
|
+
Stripe::Plan.retrieve stripe_id
|
106
|
+
end
|
94
107
|
end
|
95
108
|
end
|
96
|
-
end
|
97
109
|
|
98
|
-
|
99
|
-
|
110
|
+
def expire_stripe_data
|
111
|
+
Rails.cache.delete("#{stripe_id}/stripe_data")
|
112
|
+
end
|
100
113
|
end
|
101
|
-
|
102
|
-
end
|
114
|
+
end
|
@@ -1,13 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module PaidUp
|
2
|
+
# Plan-FeatureSetting Relationship
|
3
|
+
class PlanFeatureSetting < ActiveRecord::Base
|
4
|
+
belongs_to(
|
5
|
+
:plan,
|
6
|
+
class_name: 'PaidUp::Plan',
|
7
|
+
foreign_key: 'paid_up_plan_id',
|
8
|
+
inverse_of: :plan_feature_settings
|
9
|
+
)
|
10
|
+
validates_presence_of :setting, :plan, :feature
|
4
11
|
|
5
|
-
|
12
|
+
after_initialize :catch_unlimited_in_setting
|
13
|
+
|
14
|
+
private
|
6
15
|
|
7
|
-
private
|
8
16
|
def catch_unlimited_in_setting
|
9
|
-
|
10
|
-
self.setting = PaidUp::Unlimited
|
11
|
-
end
|
17
|
+
setting == PaidUp::Unlimited.to_i(:db) &&
|
18
|
+
(self.setting = PaidUp::Unlimited)
|
12
19
|
end
|
13
|
-
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,15 +1,17 @@
|
|
1
|
-
module PaidUp
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
module PaidUp
|
2
|
+
# Unlimited class: designed to output as 'Unlimited' for string, -1 for db,
|
3
|
+
# or 999999999 for number.
|
4
|
+
module Unlimited
|
5
|
+
def self.initialize
|
6
|
+
999_999_999
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_i(format = :default)
|
10
|
+
format == :db ? -1 : 999_999_999
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.to_s
|
14
|
+
:unlimited.l
|
10
15
|
end
|
11
16
|
end
|
12
|
-
|
13
|
-
:unlimited.l
|
14
|
-
end
|
15
|
-
end
|
17
|
+
end
|