billingly 0.1.6 → 0.1.7

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.
@@ -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