billingly 0.1.10 → 0.1.11
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.
- data/README.md +1 -1
- data/app/controllers/billingly/redemptions_controller.rb +7 -0
- data/app/controllers/billingly/redemptions_controller_base.rb +47 -0
- data/app/controllers/billingly/subscriptions_controller.rb +1 -1
- data/app/models/billingly/base_customer.rb +3 -4
- data/app/models/billingly/base_plan.rb +1 -1
- data/app/models/billingly/special_plan_code.rb +8 -0
- data/app/views/billingly/redemptions/new.html.haml +6 -0
- data/config/locales/en.yml +4 -0
- data/lib/billingly/engine.rb +15 -0
- data/lib/billingly/rails/routes.rb +2 -0
- data/lib/billingly/version.rb +1 -1
- data/lib/generators/templates/create_billingly_tables.rb +1 -1
- metadata +32 -18
data/README.md
CHANGED
@@ -34,5 +34,5 @@ Billingly does not receive payments directly (from Paypal, or Worldpay for examp
|
|
34
34
|
* Explore the [Docs](http://rubydoc.info/github/nubis/billingly/master/frames/file/README.md).
|
35
35
|
|
36
36
|
# License
|
37
|
-
MIT License. Copyright 2012 Nubis (
|
37
|
+
MIT License. Copyright 2012 Nubis (yo@nubis.im)
|
38
38
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# People who have a {Billingly::SpecialPlanCode SpecialPlanCode} can redeem it through
|
2
|
+
# the {Billingly::RedemptionsController}
|
3
|
+
class Billingly::RedemptionsControllerBase < ::ApplicationController
|
4
|
+
def new
|
5
|
+
end
|
6
|
+
|
7
|
+
def create
|
8
|
+
code = Billingly::SpecialPlanCode.find_redeemable(params[:promo_code])
|
9
|
+
if code.nil?
|
10
|
+
flash[:invalid_promo_code] = t('billingly.promo_codes.invalid')
|
11
|
+
redirect_to new_redemption_path
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
unless current_customer
|
16
|
+
session[:current_promo_code] = params[:promo_code]
|
17
|
+
on_redemption_by_non_customer
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
unless current_customer.can_subscribe_to?(code.plan)
|
22
|
+
flash[:invalid_promo_code_plan] = t('billingly.promo_codes.cannot_subscribe_to_plan')
|
23
|
+
redirect_to new_redemption_path
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
current_customer.redeem_special_plan_code(code)
|
28
|
+
on_redemption
|
29
|
+
end
|
30
|
+
|
31
|
+
# When a code is redeemed successfully by the current customer this callback is called.
|
32
|
+
# The default behavior is redirecting to the subscriptions index page.
|
33
|
+
def on_redemption
|
34
|
+
redirect_to subscriptions_path, notice: t('billingly.promo_codes.redeemed_successfully')
|
35
|
+
end
|
36
|
+
|
37
|
+
# The redemptions page is public, therefore there may be people redeeming valid codes
|
38
|
+
# without being a customer.
|
39
|
+
#
|
40
|
+
# In such cases, the validated code is stored in the session and this callback is called.
|
41
|
+
# You should redirect to your signup page here, and subscribe the customer using the saved
|
42
|
+
# code after they sign up.
|
43
|
+
# The code and plan associated to this code can be retrieved using {#current_promo_code}
|
44
|
+
# and {#current_promo_code_plan}
|
45
|
+
def on_redemption_by_non_customer
|
46
|
+
end
|
47
|
+
end
|
@@ -8,7 +8,7 @@ class Billingly::SubscriptionsController < ::ApplicationController
|
|
8
8
|
# It's likely the only reachable page for deactivated customers.
|
9
9
|
def index
|
10
10
|
@subscription = current_customer.active_subscription
|
11
|
-
@plans = Billingly::Plan.
|
11
|
+
@plans = Billingly::Plan.where('hidden = false')
|
12
12
|
@invoices = current_customer.invoices.order('created_at DESC')
|
13
13
|
end
|
14
14
|
|
@@ -133,10 +133,9 @@ module Billingly
|
|
133
133
|
|
134
134
|
# Customers can subscribe to a plan using a special subscription code which would
|
135
135
|
# allow them to access an otherwise hidden plan.
|
136
|
-
#
|
137
|
-
|
138
|
-
|
139
|
-
return if code.nil?
|
136
|
+
# The {SpecialPlanCode} can also contain an amount to be redeemed.
|
137
|
+
# @param code [SpecialPlanCode] The code being redeemed.
|
138
|
+
def redeem_special_plan_code(code)
|
140
139
|
return if code.redeemed?
|
141
140
|
credit_payment(code.bonus_amount) if code.bonus_amount
|
142
141
|
subscribe_to_plan(code.plan)
|
@@ -5,7 +5,7 @@ module Billingly
|
|
5
5
|
self.table_name = 'billingly_plans'
|
6
6
|
|
7
7
|
attr_accessible :name, :plan_code, :description, :periodicity,
|
8
|
-
:amount, :payable_upfront, :grace_period
|
8
|
+
:amount, :payable_upfront, :grace_period, :hidden
|
9
9
|
|
10
10
|
has_duration :grace_period
|
11
11
|
validates :grace_period, presence: true
|
@@ -57,4 +57,12 @@ class Billingly::SpecialPlanCode < ActiveRecord::Base
|
|
57
57
|
def self.cleanup_exported_files
|
58
58
|
`rm #{File.expand_path('~/ean_13_codes_for_*.csv')}`
|
59
59
|
end
|
60
|
+
|
61
|
+
# Shorthand finder for a redeemable code.
|
62
|
+
# This means that the code exists and has not been redeemed yet.
|
63
|
+
# @param code [String] The code to lookup.
|
64
|
+
# @return [SpecialPlanCode, nil] the SpecialPlanCode instance, or nothing.
|
65
|
+
def self.find_redeemable(code)
|
66
|
+
self.find_by_code_and_redeemed_on(code, nil)
|
67
|
+
end
|
60
68
|
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
.span4.offset4
|
2
|
+
.well
|
3
|
+
%h3 Enter your Promo Code
|
4
|
+
= form_tag redemptions_path, :class => 'form-inline' do
|
5
|
+
= text_field_tag :promo_code, params[:promo_code], :class => 'input-large', :placeholder => 'Promo Code'
|
6
|
+
= submit_tag 'Redeem!', :class => 'btn btn-success btn-large'
|
data/config/locales/en.yml
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
en:
|
2
2
|
billingly:
|
3
|
+
promo_codes:
|
4
|
+
redeemed_successfully: Your promo code has been redeemed!
|
5
|
+
invalid: The promo code you entered was invalid
|
6
|
+
cannot_subscribe_to_plan: You can't subscribe to the plan provided by your promo code
|
3
7
|
your_account_was_suspended: Your account was suspended
|
4
8
|
your_invoice_is_available: Your invoice is available
|
5
9
|
payment_receipt: Payment Receipt
|
data/lib/billingly/engine.rb
CHANGED
@@ -33,6 +33,21 @@ module Billingly
|
|
33
33
|
redirect_to(subscriptions_path)
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
# When an anonymous user redeems a {SpecialPlanCode} the code is stored
|
38
|
+
# in the session. You should first sign them up and then subscribe them
|
39
|
+
# using the code they previously redeemed.
|
40
|
+
# @return [SpecialPlanCode] The instance for the code they redeemed.
|
41
|
+
def current_promo_code
|
42
|
+
@current_promo_code ||=
|
43
|
+
Billingly::SpecialPlanCode.find_redeemable(session[:current_promo_code])
|
44
|
+
end
|
45
|
+
|
46
|
+
# Shortcut for getting the plan for the current promo code, if any.
|
47
|
+
# @return [Billingly::Plan] The plan referred to by the current code.
|
48
|
+
def current_promo_code_plan
|
49
|
+
@current_promo_code.plan if @current_promo_code
|
50
|
+
end
|
36
51
|
end
|
37
52
|
|
38
53
|
helper_method :current_customer
|
@@ -8,6 +8,8 @@ class ActionDispatch::Routing::Mapper
|
|
8
8
|
post :deactivate
|
9
9
|
end
|
10
10
|
end
|
11
|
+
resources :redemptions, controller: 'billingly/redemptions', only: [:new, :create]
|
12
|
+
get 'redeem' => "billingly/redemptions#new"
|
11
13
|
end
|
12
14
|
if skope then scope(skope, as: skope, &route) else route.call end
|
13
15
|
end
|
data/lib/billingly/version.rb
CHANGED
@@ -63,7 +63,7 @@ class CreateBillinglyTables < ActiveRecord::Migration
|
|
63
63
|
t.boolean 'payable_upfront', null: false
|
64
64
|
t.string 'grace_period', null: false
|
65
65
|
t.integer 'signup_price'
|
66
|
-
t.boolean '
|
66
|
+
t.boolean 'hidden', default: false, null: false
|
67
67
|
t.timestamps
|
68
68
|
end
|
69
69
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: billingly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &70200335482980 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.2.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70200335482980
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: validates_email_format_of
|
27
|
-
requirement: &
|
27
|
+
requirement: &70200335482480 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70200335482480
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: has_duration
|
38
|
-
requirement: &
|
38
|
+
requirement: &70200335481840 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70200335481840
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: ean13
|
49
|
-
requirement: &
|
49
|
+
requirement: &70200335481100 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70200335481100
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: timecop
|
60
|
-
requirement: &
|
60
|
+
requirement: &70200335496720 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70200335496720
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: sqlite3
|
71
|
-
requirement: &
|
71
|
+
requirement: &70200335496140 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70200335496140
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rspec-rails
|
82
|
-
requirement: &
|
82
|
+
requirement: &70200335495700 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70200335495700
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: factory_girl_rails
|
93
|
-
requirement: &
|
93
|
+
requirement: &70200335495240 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,7 +98,18 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70200335495240
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: capybara
|
104
|
+
requirement: &70200335494780 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70200335494780
|
102
113
|
description: Rails Engine for SaaS subscription management. Manage subscriptions,
|
103
114
|
plan changes, free trials and more!!!
|
104
115
|
email:
|
@@ -107,6 +118,8 @@ executables: []
|
|
107
118
|
extensions: []
|
108
119
|
extra_rdoc_files: []
|
109
120
|
files:
|
121
|
+
- app/controllers/billingly/redemptions_controller.rb
|
122
|
+
- app/controllers/billingly/redemptions_controller_base.rb
|
110
123
|
- app/controllers/billingly/subscriptions_controller.rb
|
111
124
|
- app/mailers/billingly/base_mailer.rb
|
112
125
|
- app/mailers/billingly/mailer.rb
|
@@ -126,6 +139,7 @@ files:
|
|
126
139
|
- app/views/billingly/mailer/pending_notification.html.erb
|
127
140
|
- app/views/billingly/mailer/task_results.html.erb
|
128
141
|
- app/views/billingly/mailer/trial_expired_notification.html.erb
|
142
|
+
- app/views/billingly/redemptions/new.html.haml
|
129
143
|
- app/views/billingly/subscriptions/_current_subscription.html.haml
|
130
144
|
- app/views/billingly/subscriptions/_deactivation_notice.html.haml
|
131
145
|
- app/views/billingly/subscriptions/_invoice_details.html.haml
|