diff --git a/app/legacy_lib/cancel_billing_subscription.rb b/app/legacy_lib/cancel_billing_subscription.rb deleted file mode 100644 index 6ab6001d0..000000000 --- a/app/legacy_lib/cancel_billing_subscription.rb +++ /dev/null @@ -1,36 +0,0 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -module CancelBillingSubscription - # @param [Nonprofit] nonprofit - # @return [BillingSubscription] new billing subscription for the nonprofit - def self.with_stripe(nonprofit) - begin - ParamValidation.new({nonprofit: nonprofit}, { - nonprofit: {required: true, is_a: Nonprofit} - }) - rescue ParamValidation::ValidationError => e - return {json: {error: "Validation error\n #{e.message}", errors: e.data}, status: :unprocessable_entity} - end - - np_card = nonprofit.active_card - billing_subscription = nonprofit.billing_subscription - return {json: {error: "We don't have a subscription for your non-profit. Please contact support."}, status: :unprocessable_entity} if np_card.nil? || billing_subscription.nil? # stripe_customer_id on Card object - - # Cancel and delete the subscription on Stripe - begin - customer = Stripe::Customer.retrieve(np_card.stripe_customer_id) - stripe_subscription = customer.subscriptions.retrieve(billing_subscription.stripe_subscription_id) - stripe_subscription.delete(at_period_end: false) - rescue Stripe::StripeError => e - return {json: {error: "Oops! There was an error processing your subscription cancellation. Error: #{e}"}, status: :unprocessable_entity} - end - - billing_plan_id = Settings.default_bp.id - billing_subscription.update_attributes({ - billing_plan_id: billing_plan_id, - status: "active" - }) - - BillingSubscription.clear_cache(nonprofit) - {json: {}, status: :ok} - end -end diff --git a/app/legacy_lib/insert_card.rb b/app/legacy_lib/insert_card.rb index 5dc54119d..4cfc12874 100644 --- a/app/legacy_lib/insert_card.rb +++ b/app/legacy_lib/insert_card.rb @@ -4,7 +4,7 @@ module InsertCard # If a stripe_customer_id is present, then update that customer's primary source; otherwise create a new customer # @param [ActiveSupport::HashWithIndifferentAccess] card_data card data # @option card_data [Integer] holder_id the primary key of the card's holder - # @option card_data [String] holder_type the type of the card holder. Must be 'Nonprofit' or 'Supporter' + # @option card_data [String] holder_type the type of the card holder. Must be'Supporter' # @option card_data [String] stripe_card_token the card token from stripe # @option card_data [String] stripe_card_id the card id from stripe @@ -18,7 +18,7 @@ module InsertCard def self.with_stripe(card_data, stripe_account_id = nil, event_id = nil, current_user = nil) begin ParamValidation.new(card_data.to_deprecated_h.merge({event_id: event_id}), { - holder_type: {required: true, included_in: ["Nonprofit", "Supporter"]}, + holder_type: {required: true, included_in: [ "Supporter"]}, holder_id: {required: true}, stripe_card_id: {not_blank: true, required: true}, stripe_card_token: {not_blank: true, required: true}, @@ -32,15 +32,12 @@ def self.with_stripe(card_data, stripe_account_id = nil, event_id = nil, current # validate that the user is with the correct nonprofit card_data = card_data.slice(:holder_type, :holder_id, :stripe_card_id, :stripe_card_token, :name) - holder_types = {"Nonprofit" => :nonprofit, "Supporter" => :supporter} + holder_types = { "Supporter" => :supporter} holder_type = holder_types[card_data[:holder_type]] holder = nil begin - if holder_type == :nonprofit - holder = Nonprofit.select("id, email").includes(:cards).find(card_data[:holder_id]) - elsif holder_type == :supporter - holder = Supporter.select("id, email, nonprofit_id").includes(:cards, :nonprofit).find(card_data[:holder_id]) - end + holder_type == :supporter + holder = Supporter.select("id, email, nonprofit_id").includes(:cards, :nonprofit).find(card_data[:holder_id]) rescue ActiveRecord::RecordNotFound return {json: {error: "Sorry, you need to provide a nonprofit or supporter"}, status: :unprocessable_entity} end @@ -86,10 +83,7 @@ def self.with_stripe(card_data, stripe_account_id = nil, event_id = nil, current source_token = nil begin Card.transaction { - if holder_type == :nonprofit - # @type [Nonprofit] holder - card = holder.create_active_card(card_data) - elsif holder_type == :supporter + holder_type == :supporter # @type [Supporter] holder card = holder.cards.create(card_data) params = {} @@ -97,7 +91,6 @@ def self.with_stripe(card_data, stripe_account_id = nil, event_id = nil, current params[:event] = event end source_token = InsertSourceToken.create_record(card, params).token - end card.save! } rescue ActiveRecord::ActiveRecordError => e diff --git a/app/mailers/billing_subscription_mailer.rb b/app/mailers/billing_subscription_mailer.rb index 9d96b9442..bfc1b462f 100644 --- a/app/mailers/billing_subscription_mailer.rb +++ b/app/mailers/billing_subscription_mailer.rb @@ -3,7 +3,6 @@ class BillingSubscriptionMailer < BaseMailer def failed_notice(np_id) @nonprofit = Nonprofit.find(np_id) @billing_subscription = @nonprofit.billing_subscription - @card = @nonprofit.active_card @billing_plan = @billing_subscription.billing_plan @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) mail(to: @emails, subject: "Action Needed, Please Update Your #{Settings.general.name} Account") diff --git a/app/models/card.rb b/app/models/card.rb index b0d33c2a2..4e87cf112 100755 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -9,13 +9,11 @@ class Card < ApplicationRecord :stripe_card_token, # str :stripe_card_id, # str :stripe_customer_id, # str - :holder, :holder_id, :holder_type, # polymorphic cardholder association - :inactive # a card is inactive. This is currently only meaningful for nonprofit cards - - scope :amex_only, -> { where("cards.name ILIKE ? OR cards.name ILIKE ?", "American Express%", "amex%") } + :holder, :holder_id, :holder_type # polymorphic cardholder association + + scope :amex_only, -> { where("cards.name ILIKE ? OR cards.name ILIKE ?", "American Express%", "amex%") } scope :not_amex, -> { where("cards.name NOT ILIKE ? AND cards.name NOT ILIKE ?", "American Express%", "amex%") } - scope :held_by_nonprofits, -> { where("cards.holder_type = ? ", "Nonprofit") } scope :held_by_supporters, -> { where("cards.holder_type = ? ", "Supporter") } attr_accessor :failure_message diff --git a/app/models/nonprofit.rb b/app/models/nonprofit.rb index 325410fa3..2a068c1da 100755 --- a/app/models/nonprofit.rb +++ b/app/models/nonprofit.rb @@ -143,7 +143,6 @@ def for_export_enumerable(query, chunk_limit = 15000) has_many :activities, as: :host, dependent: :destroy has_many :imports has_many :email_settings - has_many :cards, as: :holder has_many :supporter_cards, through: :supporters, source: :cards, class_name: "Card" has_many :periodic_reports has_many :export_formats @@ -269,33 +268,6 @@ def can_process_charge? !nonprofit_deactivation&.deactivated) end - def active_cards - cards.where("COALESCE(cards.inactive, FALSE) = FALSE") - end - - # @param [Card] card the new active_card - def active_card=(card) - unless card.class == Card - raise ArgumentError.new "Pass a card to active_card or else" - end - Card.transaction do - active_cards.update_all inactive: true - return cards << card - end - end - - def active_card - active_cards.first - end - - def create_active_card(card_data) - if card_data[:inactive] - raise ArgumentError.new "This method is for creating active cards only" - end - active_cards.update_all inactive: true - cards.create(card_data) - end - def currency_symbol Settings.intntl.all_currencies.find { |i| i.abbv.downcase == currency.downcase }&.symbol end diff --git a/app/views/settings/_pricing.html.erb b/app/views/settings/_pricing.html.erb index 09265f53c..4909bca76 100644 --- a/app/views/settings/_pricing.html.erb +++ b/app/views/settings/_pricing.html.erb @@ -15,13 +15,8 @@
<% end %> - <% if @nonprofit.active_card %> -Current payment method for your nonprofit: - <%= @nonprofit.active_card.name %> -
- <% end %> +If you have any questions about your current plan, please contact <%= Settings.devise.mailer_sender %>
diff --git a/spec/factories/nonprofits.rb b/spec/factories/nonprofits.rb index c2c709b41..5df35f0be 100644 --- a/spec/factories/nonprofits.rb +++ b/spec/factories/nonprofits.rb @@ -10,14 +10,6 @@ billing_subscription { build(:billing_subscription, billing_plan: build(:billing_plan_percentage_fee_of_2_5_percent_and_5_cents_flat)) } vetted { true } - factory :nonprofit_with_cards do - after(:create) { |nonprofit, evaluator| - create(:active_card_1, holder: nonprofit) - create(:active_card_2, holder: nonprofit) - create(:inactive_card, holder: nonprofit) - } - end - factory :nonprofit_with_billing_plan_percentage_fee_of_2_5_percent_and_5_cents_flat do end diff --git a/spec/factory_specs/nonprofits_spec.rb b/spec/factory_specs/nonprofits_spec.rb index edaf17c32..f3606640d 100644 --- a/spec/factory_specs/nonprofits_spec.rb +++ b/spec/factory_specs/nonprofits_spec.rb @@ -1,25 +1,4 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require "rails_helper" describe "nonprofits factory" do - describe :with_billing_subscription_on_stripe do - it "creates one Nonprofit" do - create(:nonprofit_base, :with_billing_subscription_on_stripe) - expect(Nonprofit.count).to eq 1 - end - - it "creates one BillingSubscription" do - create(:nonprofit_base, :with_billing_subscription_on_stripe) - expect(BillingSubscription.count).to eq 1 - end - - it "creates 1 BillingPlan" do - create(:nonprofit_base, :with_billing_subscription_on_stripe) - expect(BillingPlan.count).to eq 1 - end - - it "creates 1 Card" do - create(:nonprofit_base, :with_billing_subscription_on_stripe) - expect(Card.count).to eq 1 - end - end end diff --git a/spec/factory_specs/nonprofits_specs.rb b/spec/factory_specs/nonprofits_specs.rb index fb99066b0..f3606640d 100644 --- a/spec/factory_specs/nonprofits_specs.rb +++ b/spec/factory_specs/nonprofits_specs.rb @@ -1,10 +1,4 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require "rails_helper" describe "nonprofits factory" do - describe :with_billing_subscription_on_stripe do - it { - nonprofit = create(:nonprofit_base, :with_billing_subscription_on_stripe) - expect(nonprofit).to have_attributes(attributes_for(:nonprofit_base, :with_billing_subscription_on_stripe)) - } - end end diff --git a/spec/lib/cancel_billing_subscriptions_spec.rb b/spec/lib/cancel_billing_subscriptions_spec.rb deleted file mode 100644 index af9f69fe1..000000000 --- a/spec/lib/cancel_billing_subscriptions_spec.rb +++ /dev/null @@ -1,164 +0,0 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require "rails_helper" - -describe CancelBillingSubscription do - around(:each) do |example| - StripeMockHelper.mock do - example.run - end - end - - describe "parameter validation" do - describe "with no parameters" do - it "has unprocessable status" do - result = CancelBillingSubscription.with_stripe(nil) - - expect(result[:status]).to eq :unprocessable_entity - end - - it "has 2 validation errors" do - # with_stripe_mock do - - result = CancelBillingSubscription.with_stripe(nil) - errors = result[:json][:errors] - expect(errors.length).to eq(2) - expect_validation_errors(errors, [ - {key: :nonprofit, name: :required}, - {key: :nonprofit, name: :is_a} - ]) - end - end - - context "with nonprofit" do - def create_nonprofit_with_billing_subscription - create(:nonprofit_base, :with_default_billing_subscription) - end - - def create_nonprofit_without_billing_subscription - create(:nonprofit_base) - end - - def create_nonprofit_with_billing_subscription_and_active_card - create(:nonprofit_base, :with_default_billing_subscription, :with_active_card_on_stripe) - end - - it "nonprofit valid but no card or billing_subscription" do - nonprofit = create_nonprofit_without_billing_subscription - result = CancelBillingSubscription.with_stripe(nonprofit) - expect_proper_failure(result) - end - - it "nonprofit valid but no card" do - nonprofit = create_nonprofit_with_billing_subscription - result = CancelBillingSubscription.with_stripe(nonprofit) - expect_proper_failure(result) - end - - it "nonprofit valid but no billings subscription" do - nonprofit = create(:nonprofit_base, :with_active_card_on_stripe) - result = CancelBillingSubscription.with_stripe(nonprofit) - expect_proper_failure(result) - end - - def expect_proper_failure(result) - expect(result[:status]).to eq(:unprocessable_entity) - expect(result[:json][:error]).to start_with("We don't have a subscription for your non-profit. Please contact support.") - end - end - end - context "processing the billing subscription" do - def create_nonprofit - create(:nonprofit_base, :with_old_billing_plan_on_stripe) - end - - def create_default_plan - create(:billing_plan_base, :with_associated_stripe_plan, id: Settings.default_bp.id) - end - - describe "with a failure" do - def prepare_stripe_error - StripeMockHelper.prepare_error(Stripe::StripeError.new("some failure"), :retrieve_customer_subscription) - end - - it "has a status of :unprocessable entity" do - np = create_nonprofit - prepare_stripe_error - - result = CancelBillingSubscription.with_stripe(np) - - expect(result[:status]).to eq :unprocessable_entity - end - - it "has the correct error message " do - np = create_nonprofit - prepare_stripe_error - - result = CancelBillingSubscription.with_stripe(np) - - expect(result[:json][:error]).to start_with("Oops") - end - - it "hasnt changed the nonprofit's billing_subscription" do - np = create_nonprofit - prepare_stripe_error - - expect { CancelBillingSubscription.with_stripe(np) }.to_not change { np.reload.billing_subscription.reload } - end - - it "hasn't changed the nonprofit Stripe customer subscription" do - np = create_nonprofit - prepare_stripe_error - expect { CancelBillingSubscription.with_stripe(np) }.to_not change { Stripe::Customer.retrieve(np.active_card.stripe_customer_id) } - end - end - - describe "successfully" do - it "has status :ok" do - np = create_nonprofit - create_default_plan - result = CancelBillingSubscription.with_stripe(np) - expect(result[:status]).to eq :ok - end - - it "has empty json" do - np = create_nonprofit - create_default_plan - result = CancelBillingSubscription.with_stripe(np) - expect(result[:json]).to eq({}) - end - - it "has an active billing_subscription" do - np = create_nonprofit - create_default_plan - CancelBillingSubscription.with_stripe(np) - - expect(np.billing_subscription.status).to eq "active" - end - - it "changed billing_subscription to default" do - np = create_nonprofit - default_plan = create_default_plan - expect { CancelBillingSubscription.with_stripe(np) }.to change { np.billing_subscription.billing_plan }.to default_plan - end - - it "removed nonprofit's stripe customer subscriptions" do - np = create_nonprofit - create_default_plan - expect { CancelBillingSubscription.with_stripe(np) }.to change { Stripe::Customer.retrieve(np.active_card.stripe_customer_id).subscriptions.data }.to [] - end - end - - # it 'should succeed' do - # prepare - # result = CancelBillingSubscription::with_stripe(@np) - # expect(result[:status]).to eq :ok - # expect(result[:json]).to eq Hash.new - - # expect - # expect(@np.billing_subscription.status).to eq 'active' - # expect(@np.billing_subscription.billing_plan).to eq @default_plan - # str_customer_reloaded = Stripe::Customer.retrieve(@np.active_card.stripe_customer_id) - # expect(str_customer_reloaded.subscriptions.data.length).to eq 0 - # end - end -end diff --git a/spec/lib/insert/insert_card_spec.rb b/spec/lib/insert/insert_card_spec.rb index 4159bc4ae..44ac2a6b0 100644 --- a/spec/lib/insert/insert_card_spec.rb +++ b/spec/lib/insert/insert_card_spec.rb @@ -18,7 +18,6 @@ country: nil } } - let(:nonprofit) { force_create(:nonprofit) } let(:user) { user = force_create(:user) @@ -51,153 +50,6 @@ {key: "name", name: "not_blank"}]) end - describe "for nonprofits" do - let(:supporter) { nonprofit.supporters.first } - it "nonprofit doesn't exist" do - ret = InsertCard.with_stripe({holder_id: 3, holder_type: "Nonprofit", stripe_card_id: "card_fafjeht", stripe_card_token: stripe_card_token, name: "name"}) - expect(ret[:status]).to eq(:unprocessable_entity) - expect(ret[:json][:error]).to include("Sorry, you need to provide a nonprofit or supporter") - end - - it "should properly add nonprofit card when no card exists" do - stripe_customer = nil - expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| - stripe_customer = m.call(*args) - stripe_customer - } - card_data = {holder_type: "Nonprofit", holder_id: nonprofit.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, name: "card_name"} - orig_card = nonprofit.active_card - expect(orig_card).to be_nil - card_ret = InsertCard.with_stripe(card_data) - nonprofit.reload - card = nonprofit.active_card - - compare_card_returned_to_real(card_ret, card) - - expected_card = { - id: card.id, - name: "card_name", - stripe_card_token: stripe_card_token, - stripe_card_id: "card_88888", - holder_type: "Nonprofit", - holder_id: nonprofit.id, - stripe_customer_id: stripe_customer["id"] - }.merge(default_card_attribs).with_indifferent_access - - expect(card.attributes).to eq expected_card - - expect(Card.where("holder_id = ? and holder_type = ?", nonprofit.id, "Nonprofit").count).to eq(1) - - customer = verify_cust_added_np(card.stripe_customer_id, nonprofit.id) - expect(customer.sources.count).to eq(1) - expect(customer.sources.data[0].object).to eq("card") - expect(customer.sources.data[0].last4).to eq("9191") - expect(customer.sources.data[0].exp_year).to eq(2011) - end - - it "invalid params get ignored" do - stripe_customer = nil - expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| - stripe_customer = m.call(*args) - stripe_customer - } - card_data = {holder_type: "Nonprofit", holder_id: nonprofit.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, - name: "card_name", created_at: DateTime.new(0), updated_at: DateTime.new(0), inactive: true} - - card_ret = InsertCard.with_stripe(card_data) - - nonprofit.reload - card = Card.find(card_ret[:json][:id]) - - expect(nonprofit.active_card).to eq card - compare_card_returned_to_real(card_ret, card) - - expected_card = { - id: card.id, - name: "card_name", - stripe_card_token: stripe_card_token, - stripe_card_id: "card_88888", - holder_type: "Nonprofit", - holder_id: nonprofit.id, - stripe_customer_id: stripe_customer["id"] - }.merge(default_card_attribs).with_indifferent_access - - expect(card.attributes).to eq expected_card - end - - describe "card exists" do - before(:each) { - @first_card_tok = StripeMockHelper.generate_card_token(last4: "9999", exp_year: "2122") - @stripe_customer = Stripe::Customer.create - @stripe_customer.sources.create({token: @first_card_tok}) - } - - it "should properly add nonprofit card and make old inactive" do - stripe_customer = nil - expect(Stripe::Customer).to receive(:create).and_wrap_original { |m, *args| - stripe_customer = m.call(*args) - stripe_customer - } - first_card = nonprofit.create_active_card(stripe_card_id: "fake mcfake", stripe_card_token: @first_card_tok, name: "fake name") - - card_data = {holder_type: "Nonprofit", holder_id: nonprofit.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, name: "card_name"} - card_ret = InsertCard.with_stripe(card_data) - - nonprofit.reload - card = nonprofit.active_card - - compare_card_returned_to_real(card_ret, card) - - expected_card = { - id: card.id, - name: "card_name", - stripe_card_token: stripe_card_token, - stripe_card_id: "card_88888", - holder_type: "Nonprofit", - holder_id: nonprofit.id, - stripe_customer_id: stripe_customer["id"] - }.merge(default_card_attribs).with_indifferent_access - - expect(card.attributes).to eq expected_card - expect(Card.where("holder_id = ? and holder_type = ?", nonprofit.id, "Nonprofit").count).to eq(2) - expect(Card.where("holder_id = ? and holder_type = ? and inactive != ?", nonprofit.id, "Nonprofit", false).count).to eq(1) - - customer = verify_cust_added_np(card.stripe_customer_id, nonprofit.id) - - expect(customer.sources.count).to eq(1) - expect(customer.sources.data.any? { |s| s.object == "card" && s.last4 == "9191" && s.exp_year == 2011 }).to eq(true) - - # verify the original card didn't change - expect(nonprofit.cards.find(first_card.id).attributes.select { |k, _| k != "inactive" }).to eq first_card.attributes.select { |k, _| k != "inactive" } - - expect(nonprofit.cards.find(first_card.id).inactive).to eq true - end - end - - it "handle card errors" do - StripeMockHelper.prepare_card_error(:card_error, :new_customer) - card_data = {holder_type: "Nonprofit", holder_id: nonprofit.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, name: "card_name"} - - card_ret = InsertCard.with_stripe(card_data) - - expect(card_ret[:status]).to be :unprocessable_entity - expect(card_ret[:json][:error]).to start_with("Oops!") - end - - it "handle stripe errors" do - StripeMockHelper.prepare_error(Stripe::StripeError.new("generic stripe error"), :new_customer) - card_data = {holder_type: "Nonprofit", holder_id: nonprofit.id, stripe_card_id: "card_88888", stripe_card_token: stripe_card_token, name: "card_name"} - - card_ret = InsertCard.with_stripe(card_data) - - expect(card_ret[:status]).to eq :unprocessable_entity - expect(card_ret[:json][:error]).to start_with("Oops!") - end - - def verify_cust_added_np(stripe_customer_id, holder_id) - verify_cust_added(stripe_customer_id, holder_id, "Nonprofit") - end - end describe "for supporter" do let(:supporter) { force_create(:supporter, nonprofit: nonprofit) } @@ -205,6 +57,7 @@ def verify_cust_added_np(stripe_customer_id, holder_id) force_create(:event, nonprofit: nonprofit, end_datetime: Time.now.since(1.day)) } let(:user_not_from_nonprofit) { force_create(:user) } + def verify_cust_added_supporter(stripe_customer_id, holder_id) verify_cust_added(stripe_customer_id, holder_id, "Supporter") end diff --git a/spec/models/nonprofit_spec.rb b/spec/models/nonprofit_spec.rb index d94a8319f..92144c172 100644 --- a/spec/models/nonprofit_spec.rb +++ b/spec/models/nonprofit_spec.rb @@ -26,45 +26,6 @@ it { is_expected.to have_many(:associated_object_events).class_name("ObjectEvent") } - describe "with cards" do - around(:each) do |ex| - StripeMockHelper.start - ex.run - StripeMockHelper.stop - end - - before(:each) do - @nonprofit = create(:nonprofit_with_cards) - end - before(:each) do - cards = @nonprofit.cards.to_ary - @card1 = cards.first { |i| i.name == "card1" } - @card2 = cards.first { |i| i.name == "card2" } - @card3 = cards.first { |i| i.name == "card3" } - end - describe ".active_cards" do - it "should return all cards" do - cards = @nonprofit.active_cards - expect(cards.length).to eq(2) - end - end - describe ".active_card" do - it "should return one" do - card = @nonprofit.active_card - expect(card).to_not be_nil - end - end - describe ".create_active_card" do - it "should become active and turn others inactive" do - @nonprofit.active_cards - card = @nonprofit.create_active_card(name: "card 4") - expect(card).to_not be_nil - expect(card.name).to eq(@nonprofit.active_card.name) - expect(!card.inactive) - end - end - end - describe "#fee_coverage_option" do let(:nonprofit) { build(:nonprofit) }