From ac8e09bc11a7acb7e7a23e0f45502c591aa904b6 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Thu, 2 Nov 2017 14:02:50 +1100 Subject: [PATCH] Add credit card validation to StandingOrderForm --- app/forms/standing_order_form.rb | 9 +++ spec/forms/standing_order_form_spec.rb | 88 +++++++++++++++++++------- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/app/forms/standing_order_form.rb b/app/forms/standing_order_form.rb index a801a00431..21ad1f4d77 100644 --- a/app/forms/standing_order_form.rb +++ b/app/forms/standing_order_form.rb @@ -10,6 +10,7 @@ class StandingOrderForm delegate :schedule, :schedule_id, to: :standing_order delegate :shipping_method, :shipping_method_id, :payment_method, :payment_method_id, to: :standing_order delegate :shipping_method_id_changed?, :shipping_method_id_was, :payment_method_id_changed?, :payment_method_id_was, to: :standing_order + delegate :credit_card_id, to: :standing_order validates_presence_of :shop, :customer, :schedule, :payment_method, :shipping_method validates_presence_of :bill_address, :ship_address, :begins_at @@ -20,6 +21,7 @@ class StandingOrderForm validate :shipping_method_allowed? validate :standing_line_items_present? validate :standing_line_items_available? + validate :credit_card_ok? def initialize(standing_order, params={}, fee_calculator=nil) @standing_order = standing_order @@ -268,6 +270,13 @@ class StandingOrderForm end end + def credit_card_ok? + return unless payment_method.andand.type == "Spree::Gateway::StripeConnect" + return errors[:credit_card] << "is required" unless credit_card_id + return if customer.andand.user.andand.credit_card_ids.andand.include? credit_card_id + errors[:credit_card] << "is not available" + end + def variant_ids_for_shop_and_schedule Spree::Variant.joins(exchanges: { order_cycle: :schedules}) .where(id: standing_line_items.map(&:variant_id)) diff --git a/spec/forms/standing_order_form_spec.rb b/spec/forms/standing_order_form_spec.rb index 6c3180508d..f7fcb75c41 100644 --- a/spec/forms/standing_order_form_spec.rb +++ b/spec/forms/standing_order_form_spec.rb @@ -176,15 +176,70 @@ describe StandingOrderForm do let(:params) { { payment_method_id: new_payment_method.id } } context "and the submitted payment method is associated with the shop" do - it "voids existing payments and creates a new payment with the relevant payment method" do - expect(order.payments.reload.first.payment_method).to eq payment_method - expect(form.save).to be true - payments = order.reload.payments - expect(payments.count).to be 2 - expect(payments.with_state('void').count).to be 1 - expect(payments.with_state('checkout').count).to be 1 - expect(payments.with_state('void').first.payment_method).to eq payment_method - expect(payments.with_state('checkout').first.payment_method).to eq new_payment_method + context "and the submitted payment method is a Cash method" do + it "voids existing payments and creates a new payment with the relevant payment method" do + expect(order.payments.reload.first.payment_method).to eq payment_method + expect(form.save).to be true + payments = order.reload.payments + expect(payments.count).to be 2 + expect(payments.with_state('void').count).to be 1 + expect(payments.with_state('checkout').count).to be 1 + expect(payments.with_state('void').first.payment_method).to eq payment_method + expect(payments.with_state('checkout').first.payment_method).to eq new_payment_method + end + end + + context "and the submitted payment method is a Stripe method" do + let(:new_payment_method) { create(:stripe_payment_method, distributors: [standing_order.shop], preferred_enterprise_id: standing_order.shop.id) } + + context "with a credit card" do + let!(:user) { create(:user) } + let!(:credit_card) { create(:credit_card, user: user) } + + before do + standing_order.customer.update_attributes(user_id: user.id) + params[:credit_card_id] = credit_card.id + end + + it "voids existing payments and creates a new payment with the relevant payment method" do + expect(order.payments.reload.first.payment_method).to eq payment_method + expect(form.save).to be true + payments = order.reload.payments + expect(payments.count).to be 2 + expect(payments.with_state('void').count).to be 1 + expect(payments.with_state('checkout').count).to be 1 + expect(payments.with_state('void').first.payment_method).to eq payment_method + expect(payments.with_state('checkout').first.payment_method).to eq new_payment_method + end + end + + context "without a credit_card_id" do + it "requires a credit_card_id" do + expect(order.payments.reload.first.payment_method).to eq payment_method + expect(form.save).to be false + payments = order.reload.payments + expect(payments.count).to be 1 + expect(payments.with_state('void').count).to be 0 + expect(payments.with_state('checkout').count).to be 1 + expect(payments.with_state('checkout').first.payment_method).to eq payment_method + expect(form.errors[:credit_card]).to include "is required" + end + end + end + + context "and the submitted payment method is not a Stripe or Cash method" do + let(:params) { { payment_method_id: bogus_payment_method.id } } + + it "returns false and does not void existing payments or create a new payment" do + expect(order.payments.reload.first.payment_method).to eq payment_method + expect(form.save).to be false + payments = order.reload.payments + expect(payments.count).to be 1 + expect(payments.with_state('void').count).to be 0 + expect(payments.with_state('checkout').count).to be 1 + expect(payments.with_state('checkout').first.payment_method).to eq payment_method + expect(form.errors[:payment_method]).to include "must be a Cash or Stripe method" + end end end @@ -202,21 +257,6 @@ describe StandingOrderForm do expect(form.errors[:payment_method]).to include "is not available to #{standing_order.shop.name}" end end - - context "and the submitted payment method is not a Stripe or Cash method" do - let(:params) { { payment_method_id: bogus_payment_method.id } } - - it "returns false and does not void existing payments or create a new payment" do - expect(order.payments.reload.first.payment_method).to eq payment_method - expect(form.save).to be false - payments = order.reload.payments - expect(payments.count).to be 1 - expect(payments.with_state('void').count).to be 0 - expect(payments.with_state('checkout').count).to be 1 - expect(payments.with_state('checkout').first.payment_method).to eq payment_method - expect(form.errors[:payment_method]).to include "must be a Cash or Stripe method" - end - end end context "when the payment method on a payment is not the same as the standing order" do