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.
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/Gemfile +36 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +39 -0
- data/app/controllers/saasaparilla/admin/plans_controller.rb +87 -0
- data/app/controllers/saasaparilla/admin/subscriptions_controller.rb +34 -0
- data/app/controllers/saasaparilla/admin/transactions_controller.rb +14 -0
- data/app/controllers/saasaparilla/application_controller.rb +4 -0
- data/app/controllers/saasaparilla/billing_history_controller.rb +9 -0
- data/app/controllers/saasaparilla/contact_info_controller.rb +31 -0
- data/app/controllers/saasaparilla/credit_card_controller.rb +41 -0
- data/app/controllers/saasaparilla/invoices_controller.rb +19 -0
- data/app/controllers/saasaparilla/payments_controller.rb +71 -0
- data/app/controllers/saasaparilla/plans_controller.rb +34 -0
- data/app/controllers/saasaparilla/subscription_controller.rb +71 -0
- data/app/helpers/application_helper.rb +3 -0
- data/app/helpers/plans_helper.rb +2 -0
- data/app/helpers/saasaparilla/billing_history_helper.rb +4 -0
- data/app/mailers/saasaparilla/notifier.rb +38 -0
- data/app/models/billing_activity.rb +12 -0
- data/app/models/contact_info.rb +107 -0
- data/app/models/credit_card.rb +109 -0
- data/app/models/invoice.rb +31 -0
- data/app/models/invoice_line_item.rb +3 -0
- data/app/models/payment.rb +39 -0
- data/app/models/plan.rb +36 -0
- data/app/models/subscription.rb +363 -0
- data/app/models/transaction.rb +32 -0
- data/app/views/layouts/saasaparilla.html.haml +9 -0
- data/app/views/saasaparilla/admin/plans/_form.html.haml +45 -0
- data/app/views/saasaparilla/admin/plans/edit.html.erb +4 -0
- data/app/views/saasaparilla/admin/plans/index.html.erb +31 -0
- data/app/views/saasaparilla/admin/plans/new.html.haml +4 -0
- data/app/views/saasaparilla/admin/plans/show.html.haml +20 -0
- data/app/views/saasaparilla/admin/subscriptions/_subscription.html.haml +7 -0
- data/app/views/saasaparilla/admin/subscriptions/index.html.haml +14 -0
- data/app/views/saasaparilla/admin/subscriptions/show.html.haml +52 -0
- data/app/views/saasaparilla/admin/transactions/_transaction.html.haml +6 -0
- data/app/views/saasaparilla/admin/transactions/index.html.haml +16 -0
- data/app/views/saasaparilla/billing_history/_billing_activity.html.haml +10 -0
- data/app/views/saasaparilla/billing_history/show.html.haml +11 -0
- data/app/views/saasaparilla/contact_info/edit.html.haml +8 -0
- data/app/views/saasaparilla/credit_card/edit.html.haml +18 -0
- data/app/views/saasaparilla/invoices/show.html.haml +17 -0
- data/app/views/saasaparilla/notifier/billing_failed.html.haml +5 -0
- data/app/views/saasaparilla/notifier/billing_successful.html.haml +5 -0
- data/app/views/saasaparilla/notifier/invoice_created.html.haml +24 -0
- data/app/views/saasaparilla/notifier/pending_cancellation_notice.html.haml +6 -0
- data/app/views/saasaparilla/notifier/subscription_canceled.html.haml +4 -0
- data/app/views/saasaparilla/notifier/subscription_created.html.haml +5 -0
- data/app/views/saasaparilla/payments/edit.html.haml +10 -0
- data/app/views/saasaparilla/payments/new.html.haml +10 -0
- data/app/views/saasaparilla/payments/show.html.haml +8 -0
- data/app/views/saasaparilla/plans/edit.html.haml +34 -0
- data/app/views/saasaparilla/subscription/_contact_info_form.html.haml +19 -0
- data/app/views/saasaparilla/subscription/_credit_card_form.html.haml +10 -0
- data/app/views/saasaparilla/subscription/new.html.haml +24 -0
- data/app/views/saasaparilla/subscription/show.html.haml +73 -0
- data/autotest/discover.rb +2 -0
- data/config/routes.rb +27 -0
- data/lib/country_select/MIT-LICENSE +20 -0
- data/lib/country_select/README +15 -0
- data/lib/country_select/init.rb +1 -0
- data/lib/country_select/install.rb +2 -0
- data/lib/country_select/lib/country_select.rb +88 -0
- data/lib/country_select/uninstall.rb +1 -0
- data/lib/extensions/action_controller/base.rb +7 -0
- data/lib/extensions/active_record/nested_attributes.rb +36 -0
- data/lib/extensions/active_record/statuses.rb +16 -0
- data/lib/extensions/billable.rb +12 -0
- data/lib/generators/saasaparilla/install/install_generator.rb +29 -0
- data/lib/generators/saasaparilla/install/templates/create_saasaparilla_tables.rb +106 -0
- data/lib/generators/saasaparilla/install/templates/saasaparilla.yml +32 -0
- data/lib/initializers/auth_dot_net.rb +25 -0
- data/lib/initializers/simple_form.rb +77 -0
- data/lib/initializers/time_format.rb +3 -0
- data/lib/saasaparilla.rb +16 -0
- data/lib/saasaparilla/authentication.rb +18 -0
- data/lib/saasaparilla/authorization.rb +26 -0
- data/lib/saasaparilla/engine.rb +30 -0
- data/lib/saasaparilla/version.rb +3 -0
- data/saasaparilla.gemspec +48 -0
- data/spec/.livereload +21 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +11 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/model/user.rb +4 -0
- data/spec/dummy/app/views/layouts/application.html.erb +15 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +46 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +30 -0
- data/spec/dummy/config/environments/production.rb +49 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/simple_form.rb +77 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/locales/simple_form.en.yml +24 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config/saasaparilla.yml +32 -0
- data/spec/dummy/lib/templates/erb/scaffold/_form.html.erb +13 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/index.html +0 -0
- data/spec/dummy/public/javascripts/application.js +2 -0
- data/spec/dummy/public/javascripts/jquery.js +8374 -0
- data/spec/dummy/public/javascripts/jquery.min.js +16 -0
- data/spec/dummy/public/javascripts/rails.js +159 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/MIT-LICENSE +20 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/README +32 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/Rakefile +23 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/init.rb +1 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/install.rb +1 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/lib/authorize_net_cim_gateway_test.rb +492 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/lib/authorize_net_gateway_test.rb +133 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/lib/paypal_express_gateway_test.rb +138 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/tasks/activemerchant_testing_tasks.rake +4 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/test/activemerchant_testing_test.rb +8 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/test/test_helper.rb +3 -0
- data/spec/dummy/vendor/plugins/active_merchant_testing/uninstall.rb +1 -0
- data/spec/factories/factories.rb +75 -0
- data/spec/integration/navigation_spec.rb +9 -0
- data/spec/mailers/notifier_spec.rb +167 -0
- data/spec/models/billing_activity_spec.rb +27 -0
- data/spec/models/contact_info_spec.rb +32 -0
- data/spec/models/credit_card_spec.rb +57 -0
- data/spec/models/invoice_line_item_spec.rb +7 -0
- data/spec/models/invoice_spec.rb +25 -0
- data/spec/models/payment_spec.rb +29 -0
- data/spec/models/plan_spec.rb +16 -0
- data/spec/models/subscription_spec.rb +414 -0
- data/spec/requests/admin_plans_spec.rb +32 -0
- data/spec/requests/admin_subscriptions_spec.rb +31 -0
- data/spec/requests/billing_history_spec.rb +26 -0
- data/spec/requests/contact_info_controller_spec.rb +42 -0
- data/spec/requests/credit_cards_spec.rb +79 -0
- data/spec/requests/invoices_spec.rb +23 -0
- data/spec/requests/payments_spec.rb +89 -0
- data/spec/requests/subscription_plans_spec.rb +34 -0
- data/spec/requests/subscriptions_spec.rb +80 -0
- data/spec/spec_helper.rb +68 -0
- data/spec/spec_helpers/spec_helpers.rb +8 -0
- 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,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
|