summaryrefslogtreecommitdiff
path: root/billing
diff options
context:
space:
mode:
authorazul <azul@riseup.net>2013-10-18 00:18:03 -0700
committerazul <azul@riseup.net>2013-10-18 00:18:03 -0700
commit221532448ba4c435427ad2b5b3eca729b352c354 (patch)
tree1caa069380cb075155e97755d3d94d1274b4a9ea /billing
parentbf3b59e6807c8e4789b97232c7416093b07cccdf (diff)
parent92cb054d53aaac6864a6a805d9cdd3919f4a38bc (diff)
Merge pull request #98 from jessib/feature/billing-past-due-subscriptions
Feature/billing past due subscriptions
Diffstat (limited to 'billing')
-rw-r--r--billing/app/controllers/billing_admin_controller.rb29
-rw-r--r--billing/app/controllers/subscriptions_controller.rb19
-rw-r--r--billing/app/helpers/billing_helper.rb29
-rw-r--r--billing/app/models/customer.rb6
-rw-r--r--billing/app/views/billing_admin/show.html.haml7
-rw-r--r--billing/app/views/customer/show.html.haml2
-rw-r--r--billing/app/views/subscriptions/_subscription_details.html.haml11
-rw-r--r--billing/app/views/subscriptions/index.html.haml8
-rw-r--r--billing/app/views/subscriptions/show.html.haml2
-rw-r--r--billing/config/locales/en.yml3
-rw-r--r--billing/config/routes.rb1
-rw-r--r--billing/test/functional/customers_controller_test.rb8
-rw-r--r--billing/test/functional/subscriptions_controller_test.rb (renamed from billing/test/functional/subsciptions_controller_test.rb)0
-rw-r--r--billing/test/integration/subscription_test.rb12
14 files changed, 115 insertions, 22 deletions
diff --git a/billing/app/controllers/billing_admin_controller.rb b/billing/app/controllers/billing_admin_controller.rb
new file mode 100644
index 0000000..cd6149f
--- /dev/null
+++ b/billing/app/controllers/billing_admin_controller.rb
@@ -0,0 +1,29 @@
+class BillingAdminController < BillingBaseController
+ before_filter :authorize_admin
+
+ def show
+
+ br_atleast_90_days = Braintree::Subscription.search do |search|
+ search.days_past_due >= 90
+ end
+ @past_due_atleast_90_days = braintree_resource_collection_to_array(br_atleast_90_days)
+
+ br_all_past_due = Braintree::Subscription.search do |search|
+ search.status.is Braintree::Subscription::Status::PastDue
+ #cannot search by balance.
+ end
+ @all_past_due = braintree_resource_collection_to_array(br_all_past_due)
+
+ end
+
+ private
+
+ def braintree_resource_collection_to_array(braintree_resource_collection)
+ array = []
+ braintree_resource_collection.each do |object|
+ array << object
+ end
+ array
+ end
+
+end
diff --git a/billing/app/controllers/subscriptions_controller.rb b/billing/app/controllers/subscriptions_controller.rb
index 7689f35..01aaab4 100644
--- a/billing/app/controllers/subscriptions_controller.rb
+++ b/billing/app/controllers/subscriptions_controller.rb
@@ -1,7 +1,9 @@
class SubscriptionsController < BillingBaseController
before_filter :authorize
before_filter :fetch_subscription, :only => [:show, :destroy]
- before_filter :confirm_no_active_subscription, :only => [:new, :create]
+ before_filter :confirm_cancel_subscription, :only => [:destroy]
+ before_filter :confirm_self_or_admin, :only => [:index]
+ before_filter :confirm_no_pending_active_pastdue_subscription, :only => [:new, :create]
# for now, admins cannot create or destroy subscriptions for others:
before_filter :confirm_self, :only => [:new, :create]
@@ -16,6 +18,7 @@ class SubscriptionsController < BillingBaseController
def create
@result = Braintree::Subscription.create( :payment_method_token => params[:payment_method_token], :plan_id => params[:plan_id] )
+ #if you want to test pastdue, can add :price => '2001', :trial_period => true,:trial_duration => 1,:trial_duration_unit => "day" and then wait a day
end
def destroy
@@ -38,10 +41,14 @@ class SubscriptionsController < BillingBaseController
end
- def confirm_no_active_subscription
+ def confirm_cancel_subscription
+ access_denied unless view_context.allow_cancel_subscription(@subscription)
+ end
+
+ def confirm_no_pending_active_pastdue_subscription
@customer = Customer.find_by_user_id(@user.id)
- if subscription = @customer.subscriptions # will return active subscription, if it exists
- redirect_to subscription_path(subscription.id), :notice => 'You already have an active subscription'
+ if subscription = @customer.subscriptions # will return pending, active or pastdue subscription, if it exists
+ redirect_to user_subscription_path(@user, subscription.id), :notice => 'You already have a subscription'
end
end
@@ -49,4 +56,8 @@ class SubscriptionsController < BillingBaseController
@user == current_user
end
+ def confirm_self_or_admin
+ access_denied unless confirm_self or admin?
+ end
+
end
diff --git a/billing/app/helpers/billing_helper.rb b/billing/app/helpers/billing_helper.rb
index 3c0691f..b9e5e2e 100644
--- a/billing/app/helpers/billing_helper.rb
+++ b/billing/app/helpers/billing_helper.rb
@@ -9,6 +9,15 @@ module BillingHelper
form_for object, options, &block
end
+ def billing_top_link(user)
+ # for admins, top link will show special admin information, which has link to show their own customer information
+ if (admin? and user == current_user)
+ billing_admin_path
+ else
+ show_or_new_customer_link(user)
+ end
+ end
+
def show_or_new_customer_link(user)
# Link to show if user is admin viewing another user, or user is already a customer.
# Otherwise link to create a new customer.
@@ -19,4 +28,24 @@ module BillingHelper
end
end
+ # a bit strange to put here, but we don't have a subscription model
+ def user_for_subscription(subscription)
+
+ if (transaction = subscription.transactions.first)
+ # much quicker, but will only work if there is already a transaction associated with subscription (should generally be)
+ braintree_customer_id = transaction.customer_details.id
+ else
+ credit_card = Braintree::CreditCard.find(subscription.payment_method_token)
+ braintree_customer_id = credit_card.customer_id
+ end
+
+ customer = Customer.find_by_braintree_customer_id(braintree_customer_id)
+ user = User.find(customer.user_id)
+
+ end
+
+ def allow_cancel_subscription(subscription)
+ ['Active', 'Pending'].include? subscription.status or (admin? and subscription.status == 'Past Due')
+ end
+
end
diff --git a/billing/app/models/customer.rb b/billing/app/models/customer.rb
index f01c300..1acc7a5 100644
--- a/billing/app/models/customer.rb
+++ b/billing/app/models/customer.rb
@@ -40,19 +40,19 @@ class Customer < CouchRest::Model::Base
end
# based on 2nd parameter, either returns the single active subscription (or nil if there isn't one), or an array of all subsciptions
- def subscriptions(braintree_data=nil, only_active=true)
+ def subscriptions(braintree_data=nil, only_pending_active_pastdue=true)
self.with_braintree_data!
return unless has_payment_info?
subscriptions = []
self.default_credit_card.subscriptions.each do |sub|
- if only_active and sub.status == 'Active'
+ if only_pending_active_pastdue and ['Pending', 'Active','Past Due'].include? sub.status
return sub
else
subscriptions << sub
end
end
- only_active ? nil : subscriptions
+ only_pending_active_pastdue ? nil : subscriptions
end
end
diff --git a/billing/app/views/billing_admin/show.html.haml b/billing/app/views/billing_admin/show.html.haml
new file mode 100644
index 0000000..0382cf0
--- /dev/null
+++ b/billing/app/views/billing_admin/show.html.haml
@@ -0,0 +1,7 @@
+%legend= t(:more_than_90_days_past_due)
+= render(:partial => "subscriptions/subscription_details", :collection => @past_due_atleast_90_days, :as => 'subscription', :locals => {:show_user => true}) || t(:none)
+%legend= t(:all_past_due)
+= render(:partial => "subscriptions/subscription_details", :collection => @all_past_due, :as => 'subscription', :locals => {:show_user => true}) || t(:none)
+
+%legend= t(:your_settings)
+= link_to 'view own billing settings', show_or_new_customer_link(current_user) \ No newline at end of file
diff --git a/billing/app/views/customer/show.html.haml b/billing/app/views/customer/show.html.haml
index 243bd3b..562dc4b 100644
--- a/billing/app/views/customer/show.html.haml
+++ b/billing/app/views/customer/show.html.haml
@@ -18,7 +18,7 @@
= render :partial => "subscriptions/subscription_details", :locals => {:subscription => @active_subscription}
- else
%p
- = t(:no_active_subscription)
+ = t(:no_relevant_subscription)
- if current_user == @user
%p
.form-actions
diff --git a/billing/app/views/subscriptions/_subscription_details.html.haml b/billing/app/views/subscriptions/_subscription_details.html.haml
index 6eda7ca..6145c95 100644
--- a/billing/app/views/subscriptions/_subscription_details.html.haml
+++ b/billing/app/views/subscriptions/_subscription_details.html.haml
@@ -1,7 +1,14 @@
%p
+ - if local_assigns[:show_user]
+ User:
+ - user_to_show = user_for_subscription(subscription)
+ = link_to user_to_show.login, user_overview_path(user_to_show)
+ ID:
= link_to subscription.id, user_subscription_path(@user, subscription.id)
Balance:
- = number_to_currency(subscription.balance)
+ - color = (subscription.balance > 0) ? "red" : ""
+ %font{:color => color}
+ = number_to_currency(subscription.balance)
Bill on:
= subscription.billing_day_of_month
Start date:
@@ -11,7 +18,7 @@
Plan:
= subscription.plan_id
Price:
- = subscription.price
+ = number_to_currency(subscription.price)
- color = (subscription.status == 'Active') ? "green" : "red"
Status:
%font{:color => color}
diff --git a/billing/app/views/subscriptions/index.html.haml b/billing/app/views/subscriptions/index.html.haml
index 87771e5..3d4e8fd 100644
--- a/billing/app/views/subscriptions/index.html.haml
+++ b/billing/app/views/subscriptions/index.html.haml
@@ -1,8 +1,8 @@
%h2=t :all_subscriptions
-- active = false
+- pending_active_pastdue = false
- @subscriptions.each do |s|
- - if s.status == 'Active'
- - active = true
+ - if ['Pending', 'Active','Past Due'].include? s.status
+ - pending_active_pastdue = true
= render :partial => "subscription_details", :locals => {:subscription => s}
-- if !active and @user == current_user
+- if !pending_active_pastdue and @user == current_user
= link_to 'subscribe to plan', new_subscription_path, :class => :btn \ No newline at end of file
diff --git a/billing/app/views/subscriptions/show.html.haml b/billing/app/views/subscriptions/show.html.haml
index 39f4d1a..2699db9 100644
--- a/billing/app/views/subscriptions/show.html.haml
+++ b/billing/app/views/subscriptions/show.html.haml
@@ -3,4 +3,4 @@
Current
Subscription
= render :partial => "subscription_details", :locals => {:subscription => @subscription}
-= link_to t(:cancel_subscription), user_subscription_path(@user, @subscription.id), :confirm => t(:are_you_sure), :method => :delete, :class => 'btn btn-danger' if @subscription.status == 'Active' # permission check or should that just be on show?
+= link_to t(:cancel_subscription), user_subscription_path(@user, @subscription.id), :confirm => t(:are_you_sure), :method => :delete, :class => 'btn btn-danger' if allow_cancel_subscription(@subscription)
diff --git a/billing/config/locales/en.yml b/billing/config/locales/en.yml
index 5245b17..952cfd6 100644
--- a/billing/config/locales/en.yml
+++ b/billing/config/locales/en.yml
@@ -2,4 +2,5 @@ en:
create_new_customer: "Create a new Braintree Customer"
must_create_customer: "You must store a customer in braintree before subscribing to a plan"
subscribe: "Subscribe"
- save_customer_info: "Save Customer Information" \ No newline at end of file
+ save_customer_info: "Save Customer Information"
+ no_relevant_subscription: "No subscription which is Active, Pending, or Past Due" \ No newline at end of file
diff --git a/billing/config/routes.rb b/billing/config/routes.rb
index e024f43..dbdc24b 100644
--- a/billing/config/routes.rb
+++ b/billing/config/routes.rb
@@ -15,6 +15,7 @@ Rails.application.routes.draw do
match 'credit_card_info/confirm' => 'credit_card_info#confirm', :as => :confirm_credit_card_info
resources :subscriptions, :only => [:new, :create, :update] # index, show & destroy are within users path
+ match 'billing_admin' => 'billing_admin#show', :as => :billing_admin
#match 'transactions/:product_id/new' => 'transactions#new', :as => :new_transaction
#match 'transactions/confirm/:product_id' => 'transactions#confirm', :as => :confirm_transaction
diff --git a/billing/test/functional/customers_controller_test.rb b/billing/test/functional/customers_controller_test.rb
index d4881bf..46c33c9 100644
--- a/billing/test/functional/customers_controller_test.rb
+++ b/billing/test/functional/customers_controller_test.rb
@@ -7,10 +7,11 @@ class CustomersControllerTest < ActionController::TestCase
setup do
@user = FactoryGirl.create :user
@other_user = FactoryGirl.create :user
- FakeBraintree.clear!
- FakeBraintree.verify_all_cards!
+ #FakeBraintree.clear!
+ #FakeBraintree.verify_all_cards!
testid = 'testid'
- FakeBraintree::Customer.new({:credit_cards => [{:number=>"5105105105105100", :expiration_date=>"05/2013"}]}, {:id => testid, :merchant_id => Braintree::Configuration.merchant_id})
+ #this wasn't actually being used
+ #FakeBraintree::Customer.new({:credit_cards => [{:number=>"5105105105105100", :expiration_date=>"05/2013"}]}, {:id => testid, :merchant_id => Braintree::Configuration.merchant_id})
# any reason to call the create instance method on the FakeBraintree::Customer ?
@customer = Customer.new(:user_id => @other_user.id)
@customer.braintree_customer_id = testid
@@ -50,6 +51,7 @@ class CustomersControllerTest < ActionController::TestCase
test "show" do
+ skip "show customer"
login @other_user
# Below will fail, as when we go to fetch the customer data, Braintree::Customer.find(params[:id]) won't find the customer as it is a FakeBraintree customer.
#get :show, :id => @customer.braintree_customer_id
diff --git a/billing/test/functional/subsciptions_controller_test.rb b/billing/test/functional/subscriptions_controller_test.rb
index a6a1057..a6a1057 100644
--- a/billing/test/functional/subsciptions_controller_test.rb
+++ b/billing/test/functional/subscriptions_controller_test.rb
diff --git a/billing/test/integration/subscription_test.rb b/billing/test/integration/subscription_test.rb
index b893896..6356177 100644
--- a/billing/test/integration/subscription_test.rb
+++ b/billing/test/integration/subscription_test.rb
@@ -10,28 +10,34 @@ class SubscriptionTest < ActionDispatch::IntegrationTest
setup do
Warden.test_mode!
- @admin = stub_record :user, :admin => true
+ @admin = User.find_by_login('admin') || FactoryGirl.create(:user, login: 'admin')
@customer = stub_customer
@braintree_customer = @customer.braintree_customer
response = Braintree::Subscription.create plan_id: '5',
- payment_method_token: @braintree_customer.credit_cards.first.token
+ payment_method_token: @braintree_customer.credit_cards.first.token,
+ price: '10'
@subscription = response.subscription
Capybara.current_driver = Capybara.javascript_driver
end
teardown do
Warden.test_reset!
+ @admin.destroy
end
- test "admin can see subscription for another" do
+ test "admin can see all subscriptions for another" do
login_as @admin
@customer.stubs(:subscriptions).returns([@subscription])
+ @subscription.stubs(:balance).returns 0
visit user_subscriptions_path(@customer.user_id)
assert page.has_content?("Subscriptions")
assert page.has_content?("Status: Active")
page.save_screenshot('/tmp/subscriptions.png')
end
+ # test "user cannot see all subscriptions for other user" do
+ #end
+
#test "admin cannot add subscription for another" do
#end