billingly 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -130,6 +130,17 @@ module Billingly
130
130
  on_subscription_success
131
131
  end
132
132
  end
133
+
134
+ # Customers can subscribe to a plan using a special subscription code which would
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?
140
+ return if code.redeemed?
141
+ subscribe_to_plan(code.plan)
142
+ code.update_attributes(customer: self, redeemed_on: Time.now)
143
+ end
133
144
 
134
145
  # Callback called whenever this customer is successfully subscribed to a plan.
135
146
  # This callback does not differentiate if the customer is subscribing for the first time,
@@ -0,0 +1,60 @@
1
+ require 'set'
2
+ require 'ean13'
3
+
4
+ # A SpecialPlanCode lets the {Customer} subscribe to a plan which is hidden from regular
5
+ # customers.
6
+ # Customers would visit your site and redeem the code instead of subscribing to
7
+ # a plan directly. The code will then subscribe them to a plan with the given special pricing.
8
+ class Billingly::SpecialPlanCode < ActiveRecord::Base
9
+ belongs_to :plan
10
+ belongs_to :customer
11
+ validates :plan, presence: true
12
+ validates :code, presence: true
13
+
14
+ attr_accessible :plan, :code, :customer, :redeemed_on
15
+
16
+ # !@attribute [r] redeemed?
17
+ # @return [Boolean] Whether this code has been redeemed or not
18
+ def redeemed?
19
+ !redeemed_on.nil?
20
+ end
21
+
22
+ # Creates a list of valid random ean-13 codes.
23
+ # @param how_many [Integer] How many codes to create.
24
+ # @return [Array<String>] The list of generated ean-13 codes.
25
+ def self.generate_ean_13_codes(how_many)
26
+ randoms = Set.new
27
+ loop do
28
+ ean = EAN13.complete( (100000000000 + rand(100000000000)).to_s )
29
+ randoms << ean if ean
30
+ return randoms.to_a if randoms.size == how_many
31
+ end
32
+ end
33
+
34
+ # Generates rows in the database with codes for a specific plan.
35
+ # It creates new rows with new codes, and it makes sure that the new codes don't clash
36
+ # with pre-existing codes.
37
+ # @param plan [Plan] The plan to generate the codes for.
38
+ # @param how_many [Integer] How many new codes to issue.
39
+ def self.generate_for_plan(plan, how_many)
40
+ generate_ean_13_codes(how_many).collect do |code|
41
+ self.create!(code: code, plan: plan)
42
+ end
43
+ end
44
+
45
+ # Exports all the codes for each plan. You may export only the unused ones.
46
+ # The codes are exported into CSV files inside the current user's home directory.
47
+ # There is one file per plan. Each file contains all the available codes for a given plan.
48
+ def self.export_codes
49
+ where('redeemed_on IS NULL').group_by(&:plan).each do |plan, special_codes|
50
+ filename = "ean_13_codes_for_#{plan.description.gsub(/[^a-zA-Z0-9]/,'_')}.csv"
51
+ File.open(File.expand_path("~/#{filename}"),'w') do |file|
52
+ file.write(special_codes.collect(&:code).join("\n"))
53
+ end
54
+ end
55
+ end
56
+
57
+ def self.cleanup_exported_files
58
+ `rm #{File.expand_path('~/ean_13_codes_for_*.csv')}`
59
+ end
60
+ end
@@ -1,3 +1,3 @@
1
1
  module Billingly
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
@@ -64,6 +64,15 @@ class CreateBillinglyTables < ActiveRecord::Migration
64
64
  t.boolean 'hidden_on'
65
65
  t.timestamps
66
66
  end
67
+
68
+ create_table :billingly_special_plan_codes do |t|
69
+ t.references :plan, null: false
70
+ t.string :code
71
+ t.references :customer
72
+ t.datetime :redeemed_on
73
+ t.timestamps
74
+ end
75
+ add_index :billingly_special_plan_codes, :code, :unique => true
67
76
  end
68
77
  end
69
78
 
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.6
4
+ version: 0.1.7
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-10-23 00:00:00.000000000 Z
12
+ date: 2012-11-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70131414660960 !ruby/object:Gem::Requirement
16
+ requirement: &70221659484260 !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: *70131414660960
24
+ version_requirements: *70221659484260
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: validates_email_format_of
27
- requirement: &70131414660300 !ruby/object:Gem::Requirement
27
+ requirement: &70221659483740 !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: *70131414660300
35
+ version_requirements: *70221659483740
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: has_duration
38
- requirement: &70131414659780 !ruby/object:Gem::Requirement
38
+ requirement: &70221659499360 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,21 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70131414659780
46
+ version_requirements: *70221659499360
47
+ - !ruby/object:Gem::Dependency
48
+ name: ean13
49
+ requirement: &70221659498700 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70221659498700
47
58
  - !ruby/object:Gem::Dependency
48
59
  name: timecop
49
- requirement: &70131414659360 !ruby/object:Gem::Requirement
60
+ requirement: &70221659497480 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ! '>='
@@ -54,10 +65,10 @@ dependencies:
54
65
  version: '0'
55
66
  type: :development
56
67
  prerelease: false
57
- version_requirements: *70131414659360
68
+ version_requirements: *70221659497480
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: sqlite3
60
- requirement: &70131414658940 !ruby/object:Gem::Requirement
71
+ requirement: &70221659496980 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,10 +76,10 @@ dependencies:
65
76
  version: '0'
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *70131414658940
79
+ version_requirements: *70221659496980
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: rspec-rails
71
- requirement: &70131414674900 !ruby/object:Gem::Requirement
82
+ requirement: &70221659496400 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ! '>='
@@ -76,10 +87,10 @@ dependencies:
76
87
  version: '0'
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *70131414674900
90
+ version_requirements: *70221659496400
80
91
  - !ruby/object:Gem::Dependency
81
92
  name: factory_girl_rails
82
- requirement: &70131414674480 !ruby/object:Gem::Requirement
93
+ requirement: &70221659495600 !ruby/object:Gem::Requirement
83
94
  none: false
84
95
  requirements:
85
96
  - - ! '>='
@@ -87,7 +98,7 @@ dependencies:
87
98
  version: '0'
88
99
  type: :development
89
100
  prerelease: false
90
- version_requirements: *70131414674480
101
+ version_requirements: *70221659495600
91
102
  description: Rails Engine for SaaS subscription management. Manage subscriptions,
92
103
  plan changes, free trials and more!!!
93
104
  email:
@@ -107,6 +118,7 @@ files:
107
118
  - app/models/billingly/journal_entry.rb
108
119
  - app/models/billingly/payment.rb
109
120
  - app/models/billingly/plan.rb
121
+ - app/models/billingly/special_plan_code.rb
110
122
  - app/models/billingly/subscription.rb
111
123
  - app/models/billingly/tasks.rb
112
124
  - app/views/billingly/mailer/overdue_notification.html.erb