saasaparilla 0.1.6

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