payola-payments 1.4.0 → 1.5.0

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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +200 -0
  3. data/LICENSE +6 -0
  4. data/README.md +80 -0
  5. data/Rakefile +5 -4
  6. data/app/assets/javascripts/payola/application.js +3 -3
  7. data/app/assets/javascripts/payola/checkout_button.js +29 -19
  8. data/app/assets/javascripts/payola/subscription_checkout_button.js +7 -1
  9. data/app/assets/javascripts/payola/subscription_form_onestep.js +27 -0
  10. data/app/assets/stylesheets/payola/application.css +4 -4
  11. data/app/controllers/concerns/payola/affiliate_behavior.rb +1 -1
  12. data/app/controllers/concerns/payola/status_behavior.rb +1 -1
  13. data/app/controllers/payola/application_controller.rb +8 -0
  14. data/app/controllers/payola/cards_controller.rb +14 -14
  15. data/app/controllers/payola/customers_controller.rb +11 -12
  16. data/app/controllers/payola/subscriptions_controller.rb +16 -8
  17. data/app/controllers/payola/transactions_controller.rb +1 -1
  18. data/app/models/concerns/payola/plan.rb +2 -1
  19. data/app/models/payola/subscription.rb +5 -0
  20. data/app/services/payola/cancel_subscription.rb +6 -5
  21. data/app/services/payola/change_subscription_plan.rb +3 -1
  22. data/app/services/payola/change_subscription_quantity.rb +1 -1
  23. data/app/services/payola/create_sale.rb +12 -2
  24. data/app/services/payola/create_subscription.rb +1 -1
  25. data/app/services/payola/start_subscription.rb +9 -1
  26. data/app/services/payola/update_customer.rb +1 -1
  27. data/app/views/payola/subscriptions/_change_plan.html.erb +2 -0
  28. data/app/views/payola/subscriptions/_checkout.html.erb +1 -1
  29. data/app/views/payola/transactions/_checkout.html.erb +4 -2
  30. data/config/locales/en.yml +17 -0
  31. data/db/migrate/20151205004838_change_tax_percent_format_in_payola_subscriptions.rb +9 -0
  32. data/lib/payola.rb +6 -0
  33. data/lib/payola/version.rb +1 -1
  34. data/spec/concerns/plan_spec.rb +16 -4
  35. data/spec/controllers/payola/cards_controller_spec.rb +92 -8
  36. data/spec/controllers/payola/customers_controller_spec.rb +47 -4
  37. data/spec/controllers/payola/subscriptions_controller_spec.rb +59 -46
  38. data/spec/controllers/payola/transactions_controller_spec.rb +33 -30
  39. data/spec/dummy/Rakefile +1 -1
  40. data/spec/dummy/app/assets/javascripts/application.js +3 -3
  41. data/spec/dummy/app/assets/stylesheets/application.css +4 -4
  42. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  43. data/spec/dummy/app/views/layouts/application.html.erb +27 -11
  44. data/spec/dummy/bin/rails +1 -1
  45. data/spec/dummy/config.ru +2 -1
  46. data/spec/dummy/config/application.rb +1 -2
  47. data/spec/dummy/config/boot.rb +2 -2
  48. data/spec/dummy/config/environment.rb +1 -1
  49. data/spec/dummy/config/environments/development.rb +1 -37
  50. data/spec/dummy/config/environments/production.rb +1 -82
  51. data/spec/dummy/config/environments/rails_4/development.rb +37 -0
  52. data/spec/dummy/config/environments/rails_4/production.rb +82 -0
  53. data/spec/dummy/config/environments/rails_4/test.rb +45 -0
  54. data/spec/dummy/config/environments/rails_5/development.rb +54 -0
  55. data/spec/dummy/config/environments/rails_5/production.rb +86 -0
  56. data/spec/dummy/config/environments/rails_5/test.rb +44 -0
  57. data/spec/dummy/config/environments/test.rb +1 -45
  58. data/spec/dummy/config/initializers/assets.rb +3 -0
  59. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -1
  60. data/spec/dummy/config/initializers/new_framework_defaults.rb +26 -0
  61. data/spec/dummy/config/secrets.yml +1 -1
  62. data/spec/dummy/config/spring.rb +8 -0
  63. data/spec/dummy/db/schema.rb +9 -12
  64. data/spec/dummy/db/test.sqlite3 +0 -0
  65. data/spec/dummy/log/test.log +134732 -0
  66. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  67. data/spec/dummy/public/apple-touch-icon.png +0 -0
  68. data/spec/models/payola/env_wrapper_spec.rb +13 -0
  69. data/spec/models/payola/sale_spec.rb +7 -7
  70. data/spec/models/payola/subscription_spec.rb +8 -3
  71. data/spec/payola_spec.rb +8 -8
  72. data/spec/services/payola/cancel_subscription_spec.rb +20 -4
  73. data/spec/services/payola/change_subscription_plan_spec.rb +2 -1
  74. data/spec/services/payola/change_subscription_quantity_spec.rb +23 -7
  75. data/spec/services/payola/charge_card_spec.rb +30 -25
  76. data/spec/services/payola/invoice_failed_spec.rb +1 -0
  77. data/spec/services/payola/invoice_paid_spec.rb +1 -0
  78. data/spec/services/payola/start_subscription_spec.rb +15 -0
  79. data/spec/spec_helper.rb +4 -2
  80. data/spec/support/http_methods_with_keyword_args.rb +21 -0
  81. data/spec/support/params_helper.rb +9 -0
  82. data/spec/worker_spec.rb +2 -2
  83. metadata +41 -13
  84. data/config/database.yml.ci +0 -6
@@ -3,12 +3,12 @@
3
3
  * listed below.
4
4
  *
5
5
  * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
7
  *
8
8
  * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any styles
10
- * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
- * file per style scope.
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
12
  *
13
13
  *= require_tree .
14
14
  *= require_self
@@ -3,7 +3,7 @@ module Payola
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- before_filter :find_affiliate
6
+ before_action :find_affiliate
7
7
  end
8
8
 
9
9
  def find_affiliate
@@ -3,7 +3,7 @@ module Payola
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  def render_payola_status(object)
6
- render nothing: true, status: 404 and return unless object
6
+ head :not_found and return unless object
7
7
 
8
8
  errors = ([object.error.presence] + object.errors.full_messages).compact.to_sentence
9
9
 
@@ -1,5 +1,13 @@
1
1
  module Payola
2
2
  class ApplicationController < ::ApplicationController
3
3
  helper PriceHelper
4
+
5
+ private
6
+
7
+ def return_to
8
+ return params[:return_to] if params[:return_to]
9
+ request.headers["Referer"] or raise ActionController::RedirectBackError
10
+ end
11
+
4
12
  end
5
13
  end
@@ -1,24 +1,26 @@
1
1
  module Payola
2
2
  class CardsController < ApplicationController
3
-
4
- before_filter :check_modify_permissions, only: [:create, :destroy]
5
-
3
+
4
+ before_action :check_modify_permissions, only: [:create, :destroy]
5
+
6
6
  def create
7
7
  if params[:customer_id].present? && params[:stripeToken].present?
8
8
  Payola::CreateCard.call(params[:customer_id], params[:stripeToken])
9
- redirect_to return_to, notice: "Succesfully created new card"
9
+ flash_options = { notice: t('payola.cards.created') }
10
10
  else
11
- redirect_to return_to, alert: "Could not create new card"
12
- end
11
+ flash_options = { alert: t('payola.cards.not_created') }
12
+ end
13
+ redirect_to return_to, flash: flash_options
13
14
  end
14
15
 
15
16
  def destroy
16
17
  if params[:id].present? && params[:customer_id].present?
17
18
  Payola::DestroyCard.call(params[:id], params[:customer_id])
18
- redirect_to return_to, notice: "Succesfully removed the card"
19
+ flash_options = { notice: t('payola.cards.destroyed') }
19
20
  else
20
- redirect_to return_to, alert: "Could not remove the card"
21
- end
21
+ flash_options = { alert: t('payola.cards.not_destroyed') }
22
+ end
23
+ redirect_to return_to, flash: flash_options
22
24
  end
23
25
 
24
26
  private
@@ -27,14 +29,12 @@ module Payola
27
29
  if self.respond_to?(:payola_can_modify_customer?)
28
30
  redirect_to(
29
31
  return_to,
30
- alert: "You cannot modify this customer."
32
+ alert: t('payola.cards.not_authorized')
31
33
  ) and return unless self.payola_can_modify_customer?(params[:customer_id])
34
+ else
35
+ raise NotImplementedError.new("Please implement ApplicationController#payola_can_modify_customer?")
32
36
  end
33
37
  end
34
38
 
35
- def return_to
36
- params[:return_to] || :back
37
- end
38
-
39
39
  end
40
40
  end
@@ -1,20 +1,21 @@
1
1
  module Payola
2
2
  class CustomersController < ApplicationController
3
-
4
- before_filter :check_modify_permissions, only: [:update]
5
-
3
+
4
+ before_action :check_modify_permissions, only: [:update]
5
+
6
6
  def update
7
7
  if params[:id].present?
8
8
  Payola::UpdateCustomer.call(params[:id], customer_params)
9
- redirect_to return_to, notice: "Succesfully updated customer"
9
+ flash_options = { notice: t('payola.customers.updated') }
10
10
  else
11
- redirect_to return_to, alert: "Could not update customer"
12
- end
11
+ flash_options = { alert: t('payola.customers.not_updated') }
12
+ end
13
+ redirect_to return_to, flash: flash_options
13
14
  end
14
15
 
15
16
  private
16
17
 
17
- # Only including default_source for now, though other attributes can be used
18
+ # Only including default_source for now, though other attributes can be used
18
19
  # (https://stripe.com/docs/api#update_customer)
19
20
  def customer_params
20
21
  params.require(:customer).permit(:default_source)
@@ -24,14 +25,12 @@ module Payola
24
25
  if self.respond_to?(:payola_can_modify_customer?)
25
26
  redirect_to(
26
27
  return_to,
27
- alert: "You cannot modify this customer."
28
+ alert: t('payola.customers.not_authorized')
28
29
  ) and return unless self.payola_can_modify_customer?(params[:id])
30
+ else
31
+ raise NotImplementedError.new("Please implement ApplicationController#payola_can_modify_customer?")
29
32
  end
30
33
  end
31
34
 
32
- def return_to
33
- params[:return_to] || :back
34
- end
35
-
36
35
  end
37
36
  end
@@ -4,8 +4,8 @@ module Payola
4
4
  include Payola::StatusBehavior
5
5
  include Payola::AsyncBehavior
6
6
 
7
- before_filter :find_plan_coupon_and_quantity, only: [:create, :change_plan]
8
- before_filter :check_modify_permissions, only: [:destroy, :change_plan, :change_quantity, :update_card]
7
+ before_action :find_plan_coupon_and_quantity, only: [:create, :change_plan]
8
+ before_action :check_modify_permissions, only: [:destroy, :change_plan, :change_quantity, :update_card]
9
9
 
10
10
  def show
11
11
  show_object(Subscription)
@@ -21,15 +21,15 @@ module Payola
21
21
 
22
22
  def destroy
23
23
  subscription = Subscription.find_by!(guid: params[:guid])
24
- Payola::CancelSubscription.call(subscription, at_period_end: ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(params[:at_period_end]))
24
+ Payola::CancelSubscription.call(subscription, at_period_end: to_boolean(params[:at_period_end]))
25
25
  redirect_to confirm_subscription_path(subscription)
26
26
  end
27
27
 
28
28
  def change_plan
29
29
  @subscription = Subscription.find_by!(guid: params[:guid])
30
- Payola::ChangeSubscriptionPlan.call(@subscription, @plan)
30
+ Payola::ChangeSubscriptionPlan.call(@subscription, @plan, @quantity)
31
31
 
32
- confirm_with_message("Subscription plan updated")
32
+ confirm_with_message(t('payola.subscriptions.plan_updated'))
33
33
  end
34
34
 
35
35
  def change_quantity
@@ -37,14 +37,14 @@ module Payola
37
37
  @subscription = Subscription.find_by!(guid: params[:guid])
38
38
  Payola::ChangeSubscriptionQuantity.call(@subscription, @quantity)
39
39
 
40
- confirm_with_message("Subscription quantity updated")
40
+ confirm_with_message(t('payola.subscriptions.quantity_updated'))
41
41
  end
42
42
 
43
43
  def update_card
44
44
  @subscription = Subscription.find_by!(guid: params[:guid])
45
45
  Payola::UpdateCard.call(@subscription, params[:stripeToken])
46
46
 
47
- confirm_with_message("Card updated")
47
+ confirm_with_message(t('payola.subscriptions.card_updated'))
48
48
  end
49
49
 
50
50
  private
@@ -76,8 +76,10 @@ module Payola
76
76
  if self.respond_to?(:payola_can_modify_subscription?)
77
77
  redirect_to(
78
78
  confirm_subscription_path(subscription),
79
- alert: "You cannot modify this subscription."
79
+ alert: t('payola.subscriptions.not_authorized')
80
80
  ) and return unless self.payola_can_modify_subscription?(subscription)
81
+ else
82
+ raise NotImplementedError.new("Please implement ApplicationController#payola_can_modify_subscription?")
81
83
  end
82
84
  end
83
85
 
@@ -89,5 +91,11 @@ module Payola
89
91
  end
90
92
  end
91
93
 
94
+ TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
95
+
96
+ def to_boolean(value)
97
+ TRUE_VALUES.include?(value)
98
+ end
99
+
92
100
  end
93
101
  end
@@ -4,7 +4,7 @@ module Payola
4
4
  include Payola::StatusBehavior
5
5
  include Payola::AsyncBehavior
6
6
 
7
- before_filter :find_product_and_coupon, only: [:create]
7
+ before_action :find_product_and_coupon, only: [:create]
8
8
 
9
9
  def show
10
10
  show_object(Sale)
@@ -14,7 +14,8 @@ module Payola
14
14
 
15
15
  before_create :create_stripe_plan, if: -> { Payola.create_stripe_plans }
16
16
 
17
- has_many :subscriptions, :class_name => "Payola::Subscription"
17
+ has_many :subscriptions, :class_name => "Payola::Subscription", as: :plan,
18
+ dependent: :restrict_with_exception
18
19
 
19
20
  Payola.register_subscribable(self)
20
21
  end
@@ -101,8 +101,13 @@ module Payola
101
101
  self.canceled_at = Time.at(stripe_sub.canceled_at) if stripe_sub.canceled_at
102
102
  self.quantity = stripe_sub.quantity
103
103
  self.stripe_status = stripe_sub.status
104
+ self.amount = stripe_sub.plan.amount
105
+ self.currency = stripe_sub.plan.respond_to?(:currency) ? stripe_sub.plan.currency : Payola.default_currency
104
106
  self.cancel_at_period_end = stripe_sub.cancel_at_period_end
105
107
 
108
+ # Support for discounts is added to stripe-ruby-mock in v2.2.0, 84f08eb
109
+ self.coupon = stripe_sub.discount && stripe_sub.discount.coupon.id if stripe_sub.respond_to?(:discount)
110
+
106
111
  self.save!
107
112
  self
108
113
  end
@@ -2,15 +2,16 @@ module Payola
2
2
  class CancelSubscription
3
3
  def self.call(subscription, options = {})
4
4
  secret_key = Payola.secret_key_for_sale(subscription)
5
- Stripe.api_key = secret_key
6
5
  customer = Stripe::Customer.retrieve(subscription.stripe_customer_id, secret_key)
7
- customer.subscriptions.retrieve(subscription.stripe_id,secret_key).delete(options,secret_key)
6
+ customer.subscriptions.retrieve(subscription.stripe_id, secret_key).delete(options, secret_key)
8
7
 
9
- unless options[:at_period_end] == true
8
+ if options[:at_period_end] == true
9
+ # Store that the subscription will be canceled at the end of the billing period
10
+ subscription.update_attributes(cancel_at_period_end: true)
11
+ else
12
+ # Cancel the subscription immediately
10
13
  subscription.cancel!
11
14
  end
12
15
  end
13
-
14
16
  end
15
17
  end
16
-
@@ -1,6 +1,6 @@
1
1
  module Payola
2
2
  class ChangeSubscriptionPlan
3
- def self.call(subscription, plan, coupon_code = nil)
3
+ def self.call(subscription, plan, quantity = 1, coupon_code = nil)
4
4
  secret_key = Payola.secret_key_for_sale(subscription)
5
5
  old_plan = subscription.plan
6
6
 
@@ -9,9 +9,11 @@ module Payola
9
9
  sub.plan = plan.stripe_id
10
10
  sub.prorate = should_prorate?(subscription, plan, coupon_code)
11
11
  sub.coupon = coupon_code if coupon_code.present?
12
+ sub.quantity = quantity
12
13
  sub.save
13
14
 
14
15
  subscription.plan = plan
16
+ subscription.quantity = quantity
15
17
  subscription.save!
16
18
 
17
19
  subscription.instrument_plan_changed(old_plan)
@@ -13,7 +13,7 @@ module Payola
13
13
  subscription.quantity = quantity
14
14
  subscription.save!
15
15
 
16
- subscription.instrument_plan_changed(old_quantity)
16
+ subscription.instrument_quantity_changed(old_quantity)
17
17
 
18
18
  rescue RuntimeError, Stripe::StripeError => e
19
19
  subscription.errors[:base] << e.message
@@ -5,13 +5,23 @@ module Payola
5
5
  affiliate = params[:affiliate]
6
6
  coupon = params[:coupon]
7
7
 
8
+ if params[:stripe_customer_id].present?
9
+ customer = Stripe::Customer.retrieve(params[:stripe_customer_id], Payola.secret_key)
10
+ email = customer.email
11
+ token = customer.default_source
12
+ else
13
+ email = params[:stripeEmail]
14
+ token = params[:stripeToken]
15
+ end
16
+
8
17
  Payola::Sale.new do |s|
9
18
  s.product = product
10
- s.email = params[:stripeEmail]
11
- s.stripe_token = params[:stripeToken]
19
+ s.email = email
20
+ s.stripe_token = token
12
21
  s.affiliate_id = affiliate.try(:id)
13
22
  s.currency = product.respond_to?(:currency) ? product.currency : Payola.default_currency
14
23
  s.signed_custom_fields = params[:signed_custom_fields]
24
+ s.stripe_customer_id = customer.id if customer
15
25
 
16
26
  if coupon
17
27
  s.coupon = coupon
@@ -5,7 +5,7 @@ module Payola
5
5
  affiliate = params[:affiliate]
6
6
 
7
7
  if params[:stripe_customer_id].present?
8
- customer = Stripe::Customer.retrieve(params[:stripe_customer_id])
8
+ customer = Stripe::Customer.retrieve(params[:stripe_customer_id], Payola.secret_key)
9
9
  email = customer.email
10
10
  else
11
11
  email = params[:stripeEmail]
@@ -73,7 +73,15 @@ module Payola
73
73
  if stripe_customer_id
74
74
  # Retrieve the customer from Stripe and use it for this subscription
75
75
  customer = Stripe::Customer.retrieve(stripe_customer_id, secret_key)
76
- return customer unless customer.try(:deleted)
76
+
77
+ unless customer.try(:deleted)
78
+ if customer.default_source.nil? && subscription.stripe_token.present?
79
+ customer.source = subscription.stripe_token
80
+ customer.save
81
+ end
82
+
83
+ return customer
84
+ end
77
85
  end
78
86
 
79
87
  if subscription.plan.amount > 0 and not subscription.stripe_token.present?
@@ -3,7 +3,7 @@ module Payola
3
3
  def self.call(stripe_customer_id, options)
4
4
  secret_key = Payola.secret_key
5
5
  customer = Stripe::Customer.retrieve(stripe_customer_id, secret_key)
6
- customer.save(options)
6
+ customer.save(options.to_h)
7
7
  end
8
8
  end
9
9
  end
@@ -1,4 +1,5 @@
1
1
  <%
2
+ quantity = local_assigns.fetch :quantity, 1
2
3
  button_class = local_assigns.fetch :button_class, 'stripe-button-el'
3
4
  button_text = local_assigns.fetch :button_text, "Update Plan"
4
5
  %>
@@ -6,5 +7,6 @@
6
7
  <%= form_for subscription, method: :post, url: payola.change_subscription_plan_path(subscription) do |f| %>
7
8
  <%= hidden_field_tag 'plan_class', new_plan.plan_class %>
8
9
  <%= hidden_field_tag 'plan_id', new_plan.id %>
10
+ <%= hidden_field_tag 'quantity', quantity %>
9
11
  <%= button_tag button_text, class: button_class %>
10
12
  <% end %>
@@ -27,7 +27,7 @@
27
27
  form_id = "#{button_id}-form"
28
28
 
29
29
  currency = plan.respond_to?(:currency) ? plan.currency : Payola.default_currency
30
- tax_percent = local_assigns.fetch(:tax_percent, Payola.default_tax_percent).to_i
30
+ tax_percent = local_assigns.fetch(:tax_percent, Payola.default_tax_percent).to_f.round(2)
31
31
  stripe_customer_id = local_assigns.fetch(:stripe_customer_id, nil)
32
32
 
33
33
  error_div_id = local_assigns.fetch :error_div_id, ''
@@ -16,6 +16,7 @@
16
16
  billing_address = local_assigns.fetch :billing_address, false
17
17
  shipping_address = local_assigns.fetch :shipping_address, false
18
18
  bitcoin = local_assigns.fetch :bitcoin, false
19
+ stripe_customer_id = local_assigns.fetch :stripe_customer_id, nil
19
20
 
20
21
  sale = Payola::Sale.new(product: sellable)
21
22
 
@@ -52,7 +53,8 @@
52
53
  verify_zip_code: verify_zip_code,
53
54
  billing_address: billing_address,
54
55
  shipping_address: shipping_address,
55
- bitcoin: bitcoin
56
+ bitcoin: bitcoin,
57
+ stripe_customer_id: stripe_customer_id
56
58
  }
57
59
 
58
60
  raw_data[:signed_custom_fields] = sale.verifier.generate(custom_fields) if custom_fields
@@ -73,6 +75,6 @@
73
75
  <span class="payola-checkout-button-spinner" style="display: none; <%= button_inner_style %>">Please wait...</span>
74
76
  </button>
75
77
  <% if show_default_error_div %>
76
- <div class="payola-error-target" style="display:none", id="<%= error_div_id %>"></div>
78
+ <div class="payola-error-target" style="display: none;" id="<%= error_div_id %>"></div>
77
79
  <% end %>
78
80
  <% end %>
@@ -0,0 +1,17 @@
1
+ en:
2
+ payola:
3
+ cards:
4
+ created: Successfully created new card
5
+ not_created: Could not create new card
6
+ destroyed: Successfully removed the card
7
+ not_destroyed: Could not remove the card
8
+ not_authorized: You cannot modify this customer.
9
+ customers:
10
+ updated: Successfully updated customer
11
+ not_updated: Could not update customer
12
+ not_authorized: You cannot modify this customer.
13
+ subscriptions:
14
+ plan_updated: Subscription plan updated
15
+ quantity_updated: Subscription quantity updated
16
+ card_updated: Card updated
17
+ not_authorized: You cannot modify this subscription.
@@ -0,0 +1,9 @@
1
+ class ChangeTaxPercentFormatInPayolaSubscriptions < ActiveRecord::Migration
2
+ def up
3
+ change_column :payola_subscriptions, :tax_percent, :decimal, :precision => 4, :scale => 2
4
+ end
5
+
6
+ def down
7
+ change_column :payola_subscriptions, :tax_percent, :integer
8
+ end
9
+ end