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 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 (nubis@woobiz.com.ar)
37
+ MIT License. Copyright 2012 Nubis (yo@nubis.im)
38
38
 
@@ -0,0 +1,7 @@
1
+ # (see Billingly::RedemptionsControllerBase)
2
+ class Billingly::RedemptionsController < Billingly::RedemptionsControllerBase
3
+
4
+ def on_redemption_by_non_customer
5
+ redirect_to subscriptions_path
6
+ end
7
+ end
@@ -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.all
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
- # @param code [String] The 13 digit EAN-13 code being redeemed
137
- def redeem_special_plan_code(code_string)
138
- code = Billingly::SpecialPlanCode.find_by_code(code_string)
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'
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Billingly
2
- VERSION = "0.1.10"
2
+ VERSION = "0.1.11"
3
3
  end
@@ -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 'hidden_on'
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.10
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-05 00:00:00.000000000 Z
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: &70101883663420 !ruby/object:Gem::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: *70101883663420
24
+ version_requirements: *70200335482980
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: validates_email_format_of
27
- requirement: &70101883679240 !ruby/object:Gem::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: *70101883679240
35
+ version_requirements: *70200335482480
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: has_duration
38
- requirement: &70101883678660 !ruby/object:Gem::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: *70101883678660
46
+ version_requirements: *70200335481840
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: ean13
49
- requirement: &70101883678160 !ruby/object:Gem::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: *70101883678160
57
+ version_requirements: *70200335481100
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: timecop
60
- requirement: &70101883677620 !ruby/object:Gem::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: *70101883677620
68
+ version_requirements: *70200335496720
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
- requirement: &70101883677080 !ruby/object:Gem::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: *70101883677080
79
+ version_requirements: *70200335496140
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rspec-rails
82
- requirement: &70101883676580 !ruby/object:Gem::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: *70101883676580
90
+ version_requirements: *70200335495700
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: factory_girl_rails
93
- requirement: &70101883676080 !ruby/object:Gem::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: *70101883676080
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