saasaparilla 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +36 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.rdoc +3 -0
  6. data/Rakefile +39 -0
  7. data/app/controllers/saasaparilla/admin/plans_controller.rb +87 -0
  8. data/app/controllers/saasaparilla/admin/subscriptions_controller.rb +34 -0
  9. data/app/controllers/saasaparilla/admin/transactions_controller.rb +14 -0
  10. data/app/controllers/saasaparilla/application_controller.rb +4 -0
  11. data/app/controllers/saasaparilla/billing_history_controller.rb +9 -0
  12. data/app/controllers/saasaparilla/contact_info_controller.rb +31 -0
  13. data/app/controllers/saasaparilla/credit_card_controller.rb +41 -0
  14. data/app/controllers/saasaparilla/invoices_controller.rb +19 -0
  15. data/app/controllers/saasaparilla/payments_controller.rb +71 -0
  16. data/app/controllers/saasaparilla/plans_controller.rb +34 -0
  17. data/app/controllers/saasaparilla/subscription_controller.rb +71 -0
  18. data/app/helpers/application_helper.rb +3 -0
  19. data/app/helpers/plans_helper.rb +2 -0
  20. data/app/helpers/saasaparilla/billing_history_helper.rb +4 -0
  21. data/app/mailers/saasaparilla/notifier.rb +38 -0
  22. data/app/models/billing_activity.rb +12 -0
  23. data/app/models/contact_info.rb +107 -0
  24. data/app/models/credit_card.rb +109 -0
  25. data/app/models/invoice.rb +31 -0
  26. data/app/models/invoice_line_item.rb +3 -0
  27. data/app/models/payment.rb +39 -0
  28. data/app/models/plan.rb +36 -0
  29. data/app/models/subscription.rb +363 -0
  30. data/app/models/transaction.rb +32 -0
  31. data/app/views/layouts/saasaparilla.html.haml +9 -0
  32. data/app/views/saasaparilla/admin/plans/_form.html.haml +45 -0
  33. data/app/views/saasaparilla/admin/plans/edit.html.erb +4 -0
  34. data/app/views/saasaparilla/admin/plans/index.html.erb +31 -0
  35. data/app/views/saasaparilla/admin/plans/new.html.haml +4 -0
  36. data/app/views/saasaparilla/admin/plans/show.html.haml +20 -0
  37. data/app/views/saasaparilla/admin/subscriptions/_subscription.html.haml +7 -0
  38. data/app/views/saasaparilla/admin/subscriptions/index.html.haml +14 -0
  39. data/app/views/saasaparilla/admin/subscriptions/show.html.haml +52 -0
  40. data/app/views/saasaparilla/admin/transactions/_transaction.html.haml +6 -0
  41. data/app/views/saasaparilla/admin/transactions/index.html.haml +16 -0
  42. data/app/views/saasaparilla/billing_history/_billing_activity.html.haml +10 -0
  43. data/app/views/saasaparilla/billing_history/show.html.haml +11 -0
  44. data/app/views/saasaparilla/contact_info/edit.html.haml +8 -0
  45. data/app/views/saasaparilla/credit_card/edit.html.haml +18 -0
  46. data/app/views/saasaparilla/invoices/show.html.haml +17 -0
  47. data/app/views/saasaparilla/notifier/billing_failed.html.haml +5 -0
  48. data/app/views/saasaparilla/notifier/billing_successful.html.haml +5 -0
  49. data/app/views/saasaparilla/notifier/invoice_created.html.haml +24 -0
  50. data/app/views/saasaparilla/notifier/pending_cancellation_notice.html.haml +6 -0
  51. data/app/views/saasaparilla/notifier/subscription_canceled.html.haml +4 -0
  52. data/app/views/saasaparilla/notifier/subscription_created.html.haml +5 -0
  53. data/app/views/saasaparilla/payments/edit.html.haml +10 -0
  54. data/app/views/saasaparilla/payments/new.html.haml +10 -0
  55. data/app/views/saasaparilla/payments/show.html.haml +8 -0
  56. data/app/views/saasaparilla/plans/edit.html.haml +34 -0
  57. data/app/views/saasaparilla/subscription/_contact_info_form.html.haml +19 -0
  58. data/app/views/saasaparilla/subscription/_credit_card_form.html.haml +10 -0
  59. data/app/views/saasaparilla/subscription/new.html.haml +24 -0
  60. data/app/views/saasaparilla/subscription/show.html.haml +73 -0
  61. data/autotest/discover.rb +2 -0
  62. data/config/routes.rb +27 -0
  63. data/lib/country_select/MIT-LICENSE +20 -0
  64. data/lib/country_select/README +15 -0
  65. data/lib/country_select/init.rb +1 -0
  66. data/lib/country_select/install.rb +2 -0
  67. data/lib/country_select/lib/country_select.rb +88 -0
  68. data/lib/country_select/uninstall.rb +1 -0
  69. data/lib/extensions/action_controller/base.rb +7 -0
  70. data/lib/extensions/active_record/nested_attributes.rb +36 -0
  71. data/lib/extensions/active_record/statuses.rb +16 -0
  72. data/lib/extensions/billable.rb +12 -0
  73. data/lib/generators/saasaparilla/install/install_generator.rb +29 -0
  74. data/lib/generators/saasaparilla/install/templates/create_saasaparilla_tables.rb +106 -0
  75. data/lib/generators/saasaparilla/install/templates/saasaparilla.yml +32 -0
  76. data/lib/initializers/auth_dot_net.rb +25 -0
  77. data/lib/initializers/simple_form.rb +77 -0
  78. data/lib/initializers/time_format.rb +3 -0
  79. data/lib/saasaparilla.rb +16 -0
  80. data/lib/saasaparilla/authentication.rb +18 -0
  81. data/lib/saasaparilla/authorization.rb +26 -0
  82. data/lib/saasaparilla/engine.rb +30 -0
  83. data/lib/saasaparilla/version.rb +3 -0
  84. data/saasaparilla.gemspec +48 -0
  85. data/spec/.livereload +21 -0
  86. data/spec/dummy/Rakefile +7 -0
  87. data/spec/dummy/app/controllers/application_controller.rb +11 -0
  88. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  89. data/spec/dummy/app/model/user.rb +4 -0
  90. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  91. data/spec/dummy/config.ru +4 -0
  92. data/spec/dummy/config/application.rb +46 -0
  93. data/spec/dummy/config/boot.rb +10 -0
  94. data/spec/dummy/config/database.yml +22 -0
  95. data/spec/dummy/config/environment.rb +5 -0
  96. data/spec/dummy/config/environments/development.rb +30 -0
  97. data/spec/dummy/config/environments/production.rb +49 -0
  98. data/spec/dummy/config/environments/test.rb +39 -0
  99. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  100. data/spec/dummy/config/initializers/inflections.rb +10 -0
  101. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  102. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  103. data/spec/dummy/config/initializers/session_store.rb +8 -0
  104. data/spec/dummy/config/initializers/simple_form.rb +77 -0
  105. data/spec/dummy/config/locales/en.yml +5 -0
  106. data/spec/dummy/config/locales/simple_form.en.yml +24 -0
  107. data/spec/dummy/config/routes.rb +58 -0
  108. data/spec/dummy/config/saasaparilla.yml +32 -0
  109. data/spec/dummy/lib/templates/erb/scaffold/_form.html.erb +13 -0
  110. data/spec/dummy/public/404.html +26 -0
  111. data/spec/dummy/public/422.html +26 -0
  112. data/spec/dummy/public/500.html +26 -0
  113. data/spec/dummy/public/favicon.ico +0 -0
  114. data/spec/dummy/public/index.html +0 -0
  115. data/spec/dummy/public/javascripts/application.js +2 -0
  116. data/spec/dummy/public/javascripts/jquery.js +8374 -0
  117. data/spec/dummy/public/javascripts/jquery.min.js +16 -0
  118. data/spec/dummy/public/javascripts/rails.js +159 -0
  119. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  120. data/spec/dummy/script/rails +6 -0
  121. data/spec/dummy/vendor/plugins/active_merchant_testing/MIT-LICENSE +20 -0
  122. data/spec/dummy/vendor/plugins/active_merchant_testing/README +32 -0
  123. data/spec/dummy/vendor/plugins/active_merchant_testing/Rakefile +23 -0
  124. data/spec/dummy/vendor/plugins/active_merchant_testing/init.rb +1 -0
  125. data/spec/dummy/vendor/plugins/active_merchant_testing/install.rb +1 -0
  126. data/spec/dummy/vendor/plugins/active_merchant_testing/lib/authorize_net_cim_gateway_test.rb +492 -0
  127. data/spec/dummy/vendor/plugins/active_merchant_testing/lib/authorize_net_gateway_test.rb +133 -0
  128. data/spec/dummy/vendor/plugins/active_merchant_testing/lib/paypal_express_gateway_test.rb +138 -0
  129. data/spec/dummy/vendor/plugins/active_merchant_testing/tasks/activemerchant_testing_tasks.rake +4 -0
  130. data/spec/dummy/vendor/plugins/active_merchant_testing/test/activemerchant_testing_test.rb +8 -0
  131. data/spec/dummy/vendor/plugins/active_merchant_testing/test/test_helper.rb +3 -0
  132. data/spec/dummy/vendor/plugins/active_merchant_testing/uninstall.rb +1 -0
  133. data/spec/factories/factories.rb +75 -0
  134. data/spec/integration/navigation_spec.rb +9 -0
  135. data/spec/mailers/notifier_spec.rb +167 -0
  136. data/spec/models/billing_activity_spec.rb +27 -0
  137. data/spec/models/contact_info_spec.rb +32 -0
  138. data/spec/models/credit_card_spec.rb +57 -0
  139. data/spec/models/invoice_line_item_spec.rb +7 -0
  140. data/spec/models/invoice_spec.rb +25 -0
  141. data/spec/models/payment_spec.rb +29 -0
  142. data/spec/models/plan_spec.rb +16 -0
  143. data/spec/models/subscription_spec.rb +414 -0
  144. data/spec/requests/admin_plans_spec.rb +32 -0
  145. data/spec/requests/admin_subscriptions_spec.rb +31 -0
  146. data/spec/requests/billing_history_spec.rb +26 -0
  147. data/spec/requests/contact_info_controller_spec.rb +42 -0
  148. data/spec/requests/credit_cards_spec.rb +79 -0
  149. data/spec/requests/invoices_spec.rb +23 -0
  150. data/spec/requests/payments_spec.rb +89 -0
  151. data/spec/requests/subscription_plans_spec.rb +34 -0
  152. data/spec/requests/subscriptions_spec.rb +80 -0
  153. data/spec/spec_helper.rb +68 -0
  154. data/spec/spec_helpers/spec_helpers.rb +8 -0
  155. metadata +611 -0
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe BillingActivity do
4
+ it { should belong_to :subscription }
5
+ it { should have_one :invoice }
6
+
7
+ describe 'on charge' do
8
+ before(:each) do
9
+ plan = Factory.build(:plan, :name => "Gold", :price => 20)
10
+ contact_info = Factory.build(:contact_info)
11
+
12
+ credit_card = Factory.build(:credit_card)
13
+ @subscription = Factory(:subscription, :contact_info => contact_info, :plan => plan, :credit_card => credit_card)
14
+ end
15
+
16
+ it 'should create a new billing activity on successful charge' do
17
+ @subscription.bill!
18
+ @subscription.billing_activities.count.should == 2
19
+
20
+ end
21
+
22
+ it 'should create link to invoice in message if it has an invoice' do
23
+ @subscription.invoice!
24
+ @subscription.billing_activities.last.message.should include "<a href"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ContactInfo do
4
+
5
+ it { should belong_to :subscription }
6
+ it { should validate_presence_of :first_name}
7
+ it { should validate_presence_of :last_name}
8
+ it { should validate_presence_of :email}
9
+ it { should validate_presence_of :address}
10
+ it { should validate_presence_of :city}
11
+ it { should validate_presence_of :state}
12
+ it { should validate_presence_of :zip}
13
+ it { should validate_presence_of :country}
14
+
15
+ it 'should make full name' do
16
+ contact_info = Factory(:contact_info)
17
+ contact_info.full_name.should == "#{contact_info.first_name} #{contact_info.last_name}"
18
+ end
19
+
20
+ it 'should have a valid phone numer' do
21
+ contact_info = Factory(:contact_info)
22
+ contact_info.update_attributes :phone_area_code => "123", :phone_prefix => "123", :phone_suffix => "1234"
23
+ contact_info.should be_valid
24
+ end
25
+
26
+ it 'should have errors with an invalid phone number' do
27
+ contact_info = Factory(:contact_info)
28
+ contact_info.update_attributes :phone_area_code => "1", :phone_prefix => "1", :phone_suffix => "1"
29
+ contact_info.should_not be_valid
30
+ end
31
+
32
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe CreditCard do
4
+
5
+ it { should belong_to :subscription }
6
+
7
+
8
+ it 'should produce credit card from valid attributes' do
9
+ credit_card = Factory(:credit_card)
10
+ credit_card.active_merchant_card.class.should == ActiveMerchant::Billing::CreditCard
11
+ end
12
+
13
+ describe 'Card create' do
14
+ before(:each) do
15
+ @credit_card = Factory(:credit_card)
16
+ end
17
+ it 'should retain card number' do
18
+ @credit_card.card_number.should_not == nil
19
+ end
20
+
21
+ it 'should retain masked card number' do
22
+ @credit_card.card_number.should == "XXXXXXXXXXXX1111"
23
+ end
24
+
25
+ it 'should retain expiration date' do
26
+ @credit_card.expiration_date.should == "10/2011"
27
+ end
28
+ end
29
+
30
+
31
+ describe 'Card Update' do
32
+ before(:each) do
33
+ @plan = Factory.build(:plan, :name => "Gold", :price => 20)
34
+ @contact_info = Factory.build(:contact_info)
35
+
36
+ @credit_card = Factory.build(:credit_card)
37
+ @subscription = Factory(:subscription, :contact_info => @contact_info, :plan => @plan, :credit_card => @credit_card)
38
+ end
39
+
40
+
41
+ it 'should update card on auth.net' do
42
+ @credit_card.should_receive(:update_payment_profile)
43
+ @credit_card.update_attributes(
44
+ # :first_name =>"new",
45
+ # :last_name => "value",
46
+ :card_type => "Visa",
47
+ :card_number => "4111111111111111",
48
+ :card_verification => "545",
49
+ :expiry_month => "10",
50
+ :expiry_year => "2011")
51
+
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe InvoiceLineItem do
4
+ it { should belong_to :invoice }
5
+
6
+
7
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Invoice do
4
+ it { should belong_to :billing_activity }
5
+ it { should have_many :invoice_line_items }
6
+
7
+ describe 'on create' do
8
+
9
+ before(:all) do
10
+ plan = Factory.build(:plan, :name => "Gold", :price => 20.0)
11
+ contact_info = Factory.build(:contact_info)
12
+ credit_card = Factory.build(:credit_card)
13
+ @subscription = Factory.build(:subscription, :contact_info => contact_info, :plan => plan, :credit_card => credit_card)
14
+ @subscription.save
15
+ end
16
+
17
+ it 'should send invoice_created email' do
18
+ ActionMailer::Base.deliveries = [];
19
+ @subscription.invoice!
20
+ ActionMailer::Base.deliveries.first.subject.should =~ /Invoice Created/
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ describe Payment do
3
+ before(:each) do
4
+ @plan = Factory.build(:plan, :name => "Gold", :price => 20)
5
+ @contact_info = Factory.build(:contact_info)
6
+
7
+ @credit_card = Factory.build(:credit_card)
8
+
9
+ @subscription = Factory(:subscription, :contact_info => @contact_info, :plan => @plan, :credit_card => @credit_card)
10
+
11
+ @subscription.update_attributes(:balance => 15)
12
+ @payment = Factory(:payment, :amount => 12, :subscription => @subscription)
13
+ @user = Factory(:user, :subscription => @subscription)
14
+
15
+ end
16
+
17
+
18
+ it 'should create a successful transaction on update' do
19
+ @payment.should_receive(:charge_subscription)
20
+ @payment.save
21
+ end
22
+
23
+ it 'should set status to paid after bill!' do
24
+ @payment.save
25
+ @payment.status.should == 'paid'
26
+ end
27
+
28
+
29
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Plan do
4
+ it {should validate_presence_of :name}
5
+ it {should validate_presence_of :billing_period}
6
+ it {should validate_numericality_of :price}
7
+ it {should validate_presence_of :price}
8
+ it {should allow_mass_assignment_of [:name, :billing_period]}
9
+ it { should have_many :subscriptions}
10
+
11
+ it 'should have dynamic attributes' do
12
+ p = Factory.create(:plan)
13
+ p.update_attributes(:field_testing => "test")
14
+ p.testing.should == "test"
15
+ end
16
+ end
@@ -0,0 +1,414 @@
1
+ require 'spec_helper'
2
+
3
+ describe Subscription do
4
+
5
+ it { should have_one :contact_info }
6
+ it { should have_many :billing_activities }
7
+ it { should have_one :credit_card }
8
+
9
+ describe 'on create' do
10
+ before(:each) do
11
+ plan = Factory.build(:plan, :name => "Gold", :price => 20.0)
12
+ contact_info = Factory.build(:contact_info)
13
+ credit_card = Factory.build(:credit_card)
14
+ @subscription = Factory.build(:subscription, :contact_info => contact_info, :plan => plan, :credit_card => credit_card)
15
+ end
16
+
17
+ it 'should be invalid with invalid contact_info' do
18
+ @subscription.contact_info.update_attributes(:phone_area_code => "1", :phone_prefix => "1", :phone_suffix => "1")
19
+ @subscription.should_not be_valid
20
+ end
21
+
22
+ it 'should make parent billable if is_billable' do
23
+
24
+ user = Factory.create(:user, :subscription => @subscription)
25
+ user.billable?
26
+ user.subscription.billable.should == user
27
+ end
28
+
29
+ it 'should add cim number on create' do
30
+ @subscription.save
31
+ @subscription.customer_cim_id.should_not be_nil
32
+ end
33
+
34
+ it 'should have contact_info' do
35
+ @subscription.save
36
+ @subscription.reload
37
+ @subscription.contact_info.should_not be_nil
38
+ end
39
+
40
+ it 'should create payment profile after create' do
41
+ @subscription.save
42
+ @subscription.customer_payment_profile_id.should_not == nil
43
+ end
44
+
45
+ # it 'should have an inital balance' do
46
+ # @subscription.should_receive(:balance=).with(20.0)
47
+ # @subscription.save
48
+ # end
49
+
50
+ it 'should send subscription_created email' do
51
+ ActionMailer::Base.deliveries = [];
52
+ @subscription.save
53
+ ActionMailer::Base.deliveries.last.subject.should =~ /Subscription Created/
54
+ end
55
+
56
+ it 'should have status active' do
57
+ @subscription.save
58
+ @subscription.active?.should == true
59
+ end
60
+
61
+
62
+ it 'should have status of active after successful billing' do
63
+ @subscription.save
64
+ @subscription.stub!(:charge_amount).with(@subscription.balance).and_return true
65
+
66
+ @subscription.bill!
67
+ @subscription.active?.should == true
68
+ end
69
+
70
+ it 'should have status of overdue after unsuccessful billing' do
71
+ #Pending
72
+ # @subscription.save
73
+ # @subscription.stub!(:charge_amount).with(@subscription.balance).and_return false
74
+ #
75
+ # @subscription.do_inital_billing
76
+ # @subscription.overdue?.should == true
77
+ end
78
+
79
+ it 'should return set subscription balance to 0 on successful charge' do
80
+ @subscription.save
81
+ @subscription.bill!
82
+ @subscription.balance.should == 0
83
+
84
+ end
85
+
86
+ it 'should keep status at :ok on successful charge' do
87
+ @subscription.save
88
+ @subscription.bill!
89
+ @subscription.active?.should == true
90
+
91
+ end
92
+
93
+ it 'should charge an inital balance' do
94
+ @subscription.should_receive(:charge_amount).with(20.0)
95
+ @subscription.save
96
+ end
97
+
98
+ it 'should have an billing activity after inital charge' do
99
+ @subscription.save
100
+ @subscription.billing_activities.count.should == 1
101
+ end
102
+
103
+ it 'should set billing date after inital charge' do
104
+ @subscription.save
105
+ @subscription.billing_date.should == Date.today + 1.months
106
+ end
107
+
108
+ it 'should create a billing activity on charge' do
109
+ @subscription.save
110
+ @subscription.billing_activities.count.should == 1
111
+ @subscription.update_attributes(:balance => 30.0)
112
+ @subscription.bill!(30.00)
113
+ @subscription.billing_activities.count.should == 2
114
+ end
115
+
116
+ it 'should send billing_successful email on charge' do
117
+ ActionMailer::Base.deliveries = [];
118
+ @subscription.save
119
+ @subscription.update_attributes(:balance => 30.0)
120
+ @subscription.bill!
121
+ ActionMailer::Base.deliveries.first.subject.should =~ /Account Billing Successful/
122
+ end
123
+
124
+ it 'should subtract balance on bill!' do
125
+ @subscription.save
126
+ @subscription.billing_activities.count.should == 1
127
+ @subscription.update_attributes(:balance => 30.0)
128
+ @subscription.bill!(10.00)
129
+ @subscription.balance.should == 20.0
130
+ end
131
+ it 'should not change status if oustanding balance not paid' do
132
+ @subscription.save
133
+ @subscription.billing_activities.count.should == 1
134
+ @subscription.update_attributes(:balance => 30.0, :status => "overdue")
135
+ @subscription.bill!(10.00)
136
+ @subscription.status.should == "overdue"
137
+
138
+ end
139
+ it 'should change status if oustanding balancepaid' do
140
+ @subscription.save
141
+ @subscription.billing_activities.count.should == 1
142
+ @subscription.update_attributes(:balance => 30.0, :status => "overdue")
143
+ @subscription.bill!(30.00)
144
+ @subscription.status.should == "active"
145
+
146
+ end
147
+
148
+ it 'should set cancel status to pending_cancel' do
149
+ @subscription.save
150
+ @subscription.cancel
151
+ @subscription.status.should == "canceled"
152
+
153
+ end
154
+ it 'should return last transaction date' do
155
+ @subscription.save
156
+ @subscription.last_transaction_date.should == Date.today.to_s(:month_day_year)
157
+ end
158
+
159
+ it 'should return - if no transactions on last transaction date' do
160
+ @subscription.last_transaction_date.should == '-'
161
+ end
162
+
163
+ it 'should return plan name' do
164
+ @subscription.plan_name.should == "Gold"
165
+ end
166
+ end
167
+
168
+ describe 'on update' do
169
+ before(:each) do
170
+ @plan1 = Factory.build(:plan, :name => "Basic", :price => 10.0)
171
+ @plan2 = Factory.build(:plan, :name => "Premium", :price => 20.0)
172
+ contact_info = Factory.build(:contact_info)
173
+ credit_card = Factory.build(:credit_card)
174
+ @subscription = Factory.build(:subscription, :contact_info => contact_info, :plan => @plan1, :credit_card => credit_card)
175
+ @subscription.save
176
+ end
177
+
178
+ it 'should bill correct amount with pro-rated credit for mid-cycle upgrades' do
179
+ @subscription.update_attributes(:billing_date => Date.today + 15.days)
180
+ @subscription.update_attributes(:plan => @plan2)
181
+ @subscription.billing_activities.count.should == 2
182
+ @subscription.billing_activities.last.amount.should == 15.0
183
+ end
184
+
185
+ it 'should bill correct amount with pro-rated credit for early-cycle upgrades' do
186
+ @subscription.update_attributes(:billing_date => Date.today + 29.days)
187
+ @subscription.update_attributes(:plan => @plan2)
188
+ @subscription.billing_activities.count.should == 2
189
+ @subscription.billing_activities.last.amount.should == 10.3
190
+ end
191
+
192
+ it 'should not bill for upgrades on currently invoiced accounts' do
193
+ @subscription.update_attributes(:billing_date => Date.today + 3.days)
194
+ @subscription.update_attributes(:plan => @plan2)
195
+ @subscription.billing_activities.count.should == 1
196
+ end
197
+
198
+ it 'should reactivate canceled accounts' do
199
+ @subscription.update_attributes(:status => "canceled")
200
+ @subscription.reactivate!
201
+ @subscription.status.should == "active"
202
+ @subscription.billing_activities.count.should == 2
203
+ end
204
+
205
+
206
+ end
207
+
208
+ describe 'billing' do
209
+ before(:each) do
210
+ plan = Factory(:plan, :name => "Gold", :price => 20.0)
211
+ plan2 = Factory(:plan, :name => "Gold", :price => 20.0, :billing_period => "annually")
212
+ contact_info1 = Factory.build(:contact_info)
213
+ contact_info2 = Factory.build(:contact_info)
214
+ contact_info3 = Factory.build(:contact_info)
215
+ contact_info4 = Factory.build(:contact_info)
216
+ credit_card1 = Factory.build(:credit_card)
217
+ credit_card2 = Factory.build(:credit_card)
218
+ credit_card3 = Factory.build(:credit_card)
219
+ credit_card4 = Factory.build(:credit_card)
220
+ @subscription1 = Factory(:subscription, :contact_info => contact_info1, :plan => plan, :credit_card => credit_card1)
221
+ @subscription2 = Factory(:subscription, :contact_info => contact_info2, :plan => plan, :credit_card => credit_card2)
222
+ @subscription3 = Factory(:subscription, :contact_info => contact_info3, :plan => plan, :credit_card => credit_card3)
223
+ @subscription4 = Factory(:subscription, :contact_info => contact_info4, :plan => plan2, :credit_card => credit_card4)
224
+ @subscription1.update_attributes(:balance => 12, :billing_date => Date.today)
225
+ @subscription2.update_attributes(:balance => 12, :billing_date => Date.today)
226
+ @subscription3.update_attributes(:balance => 12, :billing_date => Date.today + 1.days)
227
+ @subscription4.update_attributes(:balance => 12, :billing_date => Date.today - 1.days)
228
+ end
229
+
230
+ it 'should find all non canceled subscriptions' do
231
+ @subscription2.cancel
232
+ Subscription.active.count.should == 3
233
+ end
234
+ it 'should find billable models' do
235
+
236
+
237
+ Subscription.active.all_billable_subscriptions(Date.today).count.should == 3
238
+ end
239
+
240
+ it 'should find invoiceable models' do
241
+ @subscription1.update_attributes(:billing_date => (Date.today + 1.days))
242
+ @subscription2.update_attributes(:billing_date => (Date.today + 6.days))
243
+ @subscription3.update_attributes(:billing_date => (Date.today + 5.days), :invoiced_on => Date.today - 1.months)
244
+ @subscription4.update_attributes(:billing_date => (Date.today + 5.days), :invoiced_on => Date.today - 2.days)
245
+ @subscriptions = Subscription.active.all_invoiceable(Date.today)
246
+ @subscriptions.count.should == 2
247
+ @subscriptions.should include @subscription1
248
+ @subscriptions.should include @subscription4
249
+ end
250
+
251
+ it 'should find billable models' do
252
+ @subscription1.update_attributes(:balance => 0)
253
+ @subscription4.update_attributes(:balance => 12, :status => "canceled")
254
+ Subscription.active.all_billable_subscriptions(Date.today).count.should == 1
255
+ end
256
+
257
+ describe 'recurring billing' do
258
+ describe 'trial period' do
259
+ before(:each) do
260
+ Saasaparilla::CONFIG["trial_period"] = 3
261
+ plan = Factory(:plan, :name => "Gold", :price => 20.0)
262
+ contact_info = Factory.build(:contact_info)
263
+ credit_card = Factory.build(:credit_card)
264
+ @subscription = Factory(:subscription, :contact_info => contact_info, :plan => plan, :credit_card => credit_card)
265
+ end
266
+ after(:each) do
267
+ Saasaparilla::CONFIG["trial_period"] = 0
268
+ end
269
+ it "should not bill on create if grace period " do
270
+
271
+ @subscription.billing_activities.count.should == 0
272
+
273
+ end
274
+ it "shouldn't charge subscrition until after trial period" do
275
+
276
+ Date.should_receive(:today).any_number_of_times.and_return(Time.now.to_date + 2.months)
277
+ Subscription.find_and_bill_recurring_subscriptions
278
+ @subscription.billing_activities.count.should == 0
279
+
280
+
281
+
282
+ end
283
+
284
+ it "should charge subscription after trial period" do
285
+ Date.should_receive(:today).any_number_of_times.and_return(Time.now.to_date + 3.months )
286
+ Subscription.find_and_bill_recurring_subscriptions
287
+ @subscription.billing_activities.count.should == 1
288
+
289
+ end
290
+
291
+ end
292
+ it 'should reset charge subscription' do
293
+ Subscription.find_and_bill_recurring_subscriptions
294
+ @subscription1.billing_activities.count.should == 2
295
+ @subscription2.billing_activities.count.should == 2
296
+ @subscription3.billing_activities.count.should == 1
297
+ @subscription4.billing_activities.count.should == 2
298
+ end
299
+
300
+ it 'should change status of subscription to overdue if failed billing' do
301
+ GATEWAYCIM.success = false
302
+ Subscription.find_and_bill_recurring_subscriptions
303
+ GATEWAYCIM.success = true
304
+ @subscription1.reload.overdue?.should == true
305
+ end
306
+
307
+
308
+
309
+ it 'should send billing_failed email if failed billing' do
310
+ GATEWAYCIM.success = false
311
+ ActionMailer::Base.deliveries = [];
312
+ @subscription2.update_attributes(:status => 'canceled')
313
+ @subscription3.update_attributes(:status => 'canceled')
314
+ @subscription4.update_attributes(:status => 'canceled')
315
+ Subscription.find_and_bill_recurring_subscriptions
316
+ ActionMailer::Base.deliveries.first.subject.should =~ /Account Billing Failed/
317
+ GATEWAYCIM.success = true
318
+ end
319
+
320
+ it 'should change status of subscription to canceled if failed over grace period' do
321
+ @subscription1.update_attributes(:billing_date => Date.today - 11.days, :status => "overdue")
322
+ GATEWAYCIM.success = false
323
+ Subscription.find_and_bill_recurring_subscriptions
324
+ GATEWAYCIM.success = true
325
+ @subscription1.reload.canceled?.should == true
326
+ end
327
+
328
+ it 'should send subscription_canceled email if failed over grace period' do
329
+ ActionMailer::Base.deliveries = [];
330
+ @subscription1.update_attributes(:billing_date => Date.today - 11.days, :status => "overdue")
331
+ @subscription2.update_attributes(:status => 'canceled')
332
+ @subscription3.update_attributes(:status => 'canceled')
333
+ @subscription4.update_attributes(:status => 'canceled')
334
+ GATEWAYCIM.success = false
335
+ Subscription.find_and_bill_recurring_subscriptions
336
+ GATEWAYCIM.success = true
337
+ ActionMailer::Base.deliveries.first.subject.should =~ /Your subscription has been canceled/
338
+ end
339
+
340
+ it 'should send pending_cancellation_notice email if failed and 1 day before over grace period' do
341
+ GATEWAYCIM.success = false
342
+ ActionMailer::Base.deliveries = [];
343
+ @subscription1.update_attributes(:billing_date => Date.today - 9.days, :status => "overdue")
344
+ @subscription2.update_attributes(:status => 'canceled')
345
+ @subscription3.update_attributes(:status => 'canceled')
346
+ @subscription4.update_attributes(:status => 'canceled')
347
+ Subscription.find_and_bill_recurring_subscriptions
348
+ ActionMailer::Base.deliveries.first.subject.should =~ /Your subscription will be canceled soon/
349
+ GATEWAYCIM.success = true
350
+ end
351
+
352
+ it 'should not change status if subscription not past grace period on failed billing' do
353
+ @subscription2.update_attributes(:billing_date => Date.today - 9.days, :status => "overdue", :overdue_on => Date.today - 9.days)
354
+ GATEWAYCIM.success = false
355
+ Subscription.find_and_bill_recurring_subscriptions
356
+ GATEWAYCIM.success = true
357
+ @subscription2.reload.overdue?.should == true
358
+ end
359
+
360
+ it 'should set overdue_on to todays date when payment failed' do
361
+ @subscription1.update_attributes(:billing_date => Date.today , :status => "active")
362
+ GATEWAYCIM.success = false
363
+ Subscription.find_and_bill_recurring_subscriptions
364
+ GATEWAYCIM.success = true
365
+ @subscription1.reload.overdue?.should == true
366
+ @subscription1.overdue_on.should == Date.today
367
+ end
368
+ it 'should set billing date to next month' do
369
+ @billing_date1_old = @subscription1.billing_date
370
+ @billing_date2_old = @subscription2.billing_date
371
+ @billing_date4_old = @subscription4.billing_date
372
+ Subscription.find_and_bill_recurring_subscriptions
373
+ @subscription1.reload.billing_date.should == @billing_date1_old + 1.months
374
+ @subscription2.reload.billing_date.should == @billing_date2_old + 1.months
375
+ @subscription4.reload.billing_date.should == @billing_date4_old + 1.years
376
+ end
377
+
378
+ it 'should set balance on invoice' do
379
+ @subscription1.balance.should == 12.0
380
+ @subscription1.invoice!
381
+ @subscription1.reload
382
+ @subscription1.balance.should == 32.0
383
+ end
384
+ it 'should create invoice on invoice' do
385
+ @subscription1.invoice!
386
+
387
+ @subscription1.billing_activities.last.invoice.should_not == nil
388
+ end
389
+
390
+ it 'should get amount on invoice after create invoice' do
391
+ @subscription1.invoice!
392
+ @subscription1.billing_activities.last.invoice.amount.should == 20.0
393
+ end
394
+ it 'should set invoiced_on after invoice' do
395
+ @subscription1.invoice!
396
+ @subscription1.invoiced_on.should == Date.today
397
+ end
398
+
399
+ it 'should set to and from date on invoice after invoice' do
400
+ @subscription1.invoice!
401
+ @subscription1.billing_activities.last.invoice.invoice_line_items.first.to.should == @subscription1.billing_date
402
+ end
403
+
404
+
405
+ end
406
+ end
407
+
408
+
409
+
410
+
411
+
412
+
413
+
414
+ end