diff --git a/app/helpers/enterprises_helper.rb b/app/helpers/enterprises_helper.rb index 701f736180..2f60c848b4 100644 --- a/app/helpers/enterprises_helper.rb +++ b/app/helpers/enterprises_helper.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'open_food_network/available_payment_method_filter' - module EnterprisesHelper def current_distributor @current_distributor ||= current_order(false)&.distributor @@ -18,18 +16,7 @@ module EnterprisesHelper end def available_payment_methods - return [] if current_distributor.blank? - - payment_methods = current_distributor.payment_methods.available(:both).to_a - - filter = OpenFoodNetwork::AvailablePaymentMethodFilter.new - filter.filter!(payment_methods) - - applicator = OpenFoodNetwork::TagRuleApplicator.new(current_distributor, - "FilterPaymentMethods", current_customer&.tag_list) - applicator.filter!(payment_methods) - - payment_methods + OrderAvailablePaymentMethods.new(current_order, current_customer).to_a end def managed_enterprises diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 9b1f60f457..adf2db9611 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -399,7 +399,7 @@ class Enterprise < ApplicationRecord end def ready_for_checkout? - shipping_methods.frontend.any? && payment_methods.available.any? + shipping_methods.frontend.any? && payment_methods.available.any?(&:configured?) end def self.find_available_permalink(test_permalink) diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb index e31fe4bf82..6e9e04607f 100644 --- a/app/models/order_cycle.rb +++ b/app/models/order_cycle.rb @@ -24,6 +24,9 @@ class OrderCycle < ApplicationRecord has_many :distributors, -> { distinct }, source: :receiver, through: :cached_outgoing_exchanges has_many :order_cycle_schedules has_many :schedules, through: :order_cycle_schedules + has_and_belongs_to_many :selected_distributor_payment_methods, + class_name: 'DistributorPaymentMethod', + join_table: 'order_cycles_distributor_payment_methods' has_and_belongs_to_many :selected_distributor_shipping_methods, class_name: 'DistributorShippingMethod', join_table: 'order_cycles_distributor_shipping_methods' @@ -152,12 +155,10 @@ class OrderCycle < ApplicationRecord ] end - def attachable_payment_methods - Spree::PaymentMethod.available(:both). - joins("INNER JOIN distributors_payment_methods - ON payment_method_id = spree_payment_methods.id"). - where("distributor_id IN (?)", distributor_ids). - distinct + def attachable_distributor_payment_methods + DistributorPaymentMethod.joins(:payment_method). + merge(Spree::PaymentMethod.available). + where("distributor_id IN (?)", distributor_ids) end def attachable_distributor_shipping_methods @@ -177,6 +178,9 @@ class OrderCycle < ApplicationRecord oc.schedule_ids = schedule_ids oc.save! exchanges.each { |e| e.clone!(oc) } + oc.selected_distributor_payment_method_ids = ( + attachable_distributor_payment_methods.map(&:id) & selected_distributor_payment_method_ids + ) oc.selected_distributor_shipping_method_ids = ( attachable_distributor_shipping_methods.map(&:id) & selected_distributor_shipping_method_ids ) @@ -293,6 +297,18 @@ class OrderCycle < ApplicationRecord items.each { |li| scoper.scope(li.variant) } end + def distributor_payment_methods + if simple? || selected_distributor_payment_methods.none? + attachable_distributor_payment_methods + else + attachable_distributor_payment_methods.where( + "distributors_payment_methods.id IN (?) OR distributor_id NOT IN (?)", + selected_distributor_payment_methods.map(&:id), + selected_distributor_payment_methods.map(&:distributor_id) + ) + end + end + def distributor_shipping_methods if simple? || selected_distributor_shipping_methods.none? attachable_distributor_shipping_methods diff --git a/app/models/spree/payment_method.rb b/app/models/spree/payment_method.rb index 4e44cae10d..d09c3c7c4c 100644 --- a/app/models/spree/payment_method.rb +++ b/app/models/spree/payment_method.rb @@ -20,6 +20,8 @@ module Spree after_initialize :init + scope :inactive_or_backend, -> { where("active = false OR display_on = 'back_end'") } + scope :production, -> { where(environment: 'production') } scope :managed_by, lambda { |user| @@ -57,6 +59,10 @@ module Spree Rails.application.config.spree.payment_methods end + def configured? + !stripe? || stripe_configured? + end + def provider_class raise 'You must implement provider_class method for this gateway.' end @@ -71,6 +77,10 @@ module Spree nil end + def frontend? + active? && display_on != "back_end" + end + # The class that will process payments for this payment type, used for @payment.source # e.g. CreditCard in the case of a the Gateway payment type # nil means the payment method doesn't require a source e.g. check @@ -120,5 +130,17 @@ module Spree def distributor_validation validates_with DistributorsValidator end + + def stripe? + type.ends_with?("StripeSCA") + end + + def stripe_configured? + Spree::Config.stripe_connect_enabled && + Stripe.publishable_key && + preferred_enterprise_id.present? && + preferred_enterprise_id > 0 && + stripe_account_id.present? + end end end diff --git a/app/services/order_available_payment_methods.rb b/app/services/order_available_payment_methods.rb new file mode 100644 index 0000000000..0e89825723 --- /dev/null +++ b/app/services/order_available_payment_methods.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +class OrderAvailablePaymentMethods + attr_reader :order, :customer + + delegate :distributor, + :order_cycle, + to: :order + + def initialize(order, customer = nil) + @order, @customer = order, customer + end + + def to_a + return [] if distributor.blank? + + payment_methods = payment_methods_before_tag_rules_applied + + applicator = OpenFoodNetwork::TagRuleApplicator.new(distributor, + "FilterPaymentMethods", customer&.tag_list) + applicator.filter!(payment_methods) + + payment_methods.uniq + end + + private + + def payment_methods_before_tag_rules_applied + if order_cycle.nil? || order_cycle.simple? + distributor.payment_methods + else + distributor.payment_methods.where( + id: order_cycle.distributor_payment_methods.select(:payment_method_id) + ) + end.available.select(&:configured?) + end +end diff --git a/app/services/order_cycle_form.rb b/app/services/order_cycle_form.rb index 252c3bc783..52a3ce10ef 100644 --- a/app/services/order_cycle_form.rb +++ b/app/services/order_cycle_form.rb @@ -12,6 +12,9 @@ class OrderCycleForm @user = user @permissions = OpenFoodNetwork::Permissions.new(user) @schedule_ids = order_cycle_params.delete(:schedule_ids) + @selected_distributor_payment_method_ids = order_cycle_params.delete( + :selected_distributor_payment_method_ids + ) @selected_distributor_shipping_method_ids = order_cycle_params.delete( :selected_distributor_shipping_method_ids ) @@ -27,6 +30,7 @@ class OrderCycleForm order_cycle.schedule_ids = schedule_ids if parameter_specified?(:schedule_ids) order_cycle.save! apply_exchange_changes + attach_selected_distributor_payment_methods attach_selected_distributor_shipping_methods sync_subscriptions true @@ -49,16 +53,29 @@ class OrderCycleForm return if exchanges_unchanged? OpenFoodNetwork::OrderCycleFormApplicator.new(order_cycle, user).go! + + # reload so outgoing exchanges are up-to-date for shipping/payment method validations + order_cycle.reload + end + + def attach_selected_distributor_payment_methods + return if @selected_distributor_payment_method_ids.nil? + + order_cycle.selected_distributor_payment_method_ids = selected_distributor_payment_method_ids + order_cycle.save! end def attach_selected_distributor_shipping_methods return if @selected_distributor_shipping_method_ids.nil? - order_cycle.reload # so outgoing exchanges are up-to-date for shipping method validations order_cycle.selected_distributor_shipping_method_ids = selected_distributor_shipping_method_ids order_cycle.save! end + def attachable_distributor_payment_method_ids + @attachable_distributor_payment_method_ids ||= order_cycle.attachable_distributor_payment_methods.map(&:id) + end + def attachable_distributor_shipping_method_ids @attachable_distributor_shipping_method_ids ||= order_cycle.attachable_distributor_shipping_methods.map(&:id) end @@ -69,6 +86,19 @@ class OrderCycleForm end end + def selected_distributor_payment_method_ids + @selected_distributor_payment_method_ids = ( + attachable_distributor_payment_method_ids & + @selected_distributor_payment_method_ids.reject(&:blank?).map(&:to_i) + ) + + if attachable_distributor_payment_method_ids.sort == @selected_distributor_payment_method_ids.sort + @selected_distributor_payment_method_ids = [] + end + + @selected_distributor_payment_method_ids + end + def selected_distributor_shipping_method_ids @selected_distributor_shipping_method_ids = ( attachable_distributor_shipping_method_ids & diff --git a/app/services/permitted_attributes/order_cycle.rb b/app/services/permitted_attributes/order_cycle.rb index 15d652268c..dc23c8e5c3 100644 --- a/app/services/permitted_attributes/order_cycle.rb +++ b/app/services/permitted_attributes/order_cycle.rb @@ -17,7 +17,8 @@ module PermittedAttributes :name, :orders_open_at, :orders_close_at, :coordinator_id, :preferred_product_selection_from_coordinator_inventory_only, :automatic_notifications, - { schedule_ids: [], selected_distributor_shipping_method_ids: [], coordinator_fee_ids: [] } + { schedule_ids: [], selected_distributor_payment_method_ids: [], + selected_distributor_shipping_method_ids: [], coordinator_fee_ids: [] } ] end diff --git a/app/views/admin/order_cycles/checkout_options.html.haml b/app/views/admin/order_cycles/checkout_options.html.haml index 32eb731895..42c3213301 100644 --- a/app/views/admin/order_cycles/checkout_options.html.haml +++ b/app/views/admin/order_cycles/checkout_options.html.haml @@ -10,8 +10,6 @@ %fieldset.no-border-bottom %legend{ align: 'center'}= t('.checkout_options') - = hidden_field_tag "order_cycle[selected_distributor_shipping_method_ids][]", "" - .row .three.columns   @@ -19,10 +17,12 @@ %table.checkout-options %thead %tr - %th{ colspan: 2 }= t('.shipping_methods') + %th{ colspan: 2 } + = t('.shipping_methods') + = hidden_field_tag "order_cycle[selected_distributor_shipping_method_ids][]", "" - @order_cycle.distributors.each do |distributor| - distributor_shipping_methods = @order_cycle.attachable_distributor_shipping_methods.where("distributor_id = ?", distributor.id).includes(:shipping_method) - %tr{ "data-controller": "select-all" } + %tr{ class: "distributor-#{distributor.id}-shipping-methods", "data-controller": "select-all" } %td.text-center - if distributor_shipping_methods.many? %label @@ -48,17 +48,36 @@ %p = t('.no_shipping_methods') %tr - %th{ colspan: 2 }= t('.payment_methods') - %tr - %td - %td - - if @order_cycle.attachable_payment_methods.available(:both).any? - %ul - - @order_cycle.attachable_payment_methods.available(:both).each do |payment_method| - %li= payment_method.name - - else - %p - = t('.no_payment_methods') + %th{ colspan: 2 } + = t('.payment_methods') + = hidden_field_tag "order_cycle[selected_distributor_payment_method_ids][]", "" + - @order_cycle.distributors.each do |distributor| + - distributor_payment_methods = @order_cycle.attachable_distributor_payment_methods.where("distributor_id = ?", distributor.id).includes(:payment_method) + %tr{ class: "distributor-#{distributor.id}-payment-methods", "data-controller": "select-all" } + %td.text-center + - if distributor_payment_methods.many? + %label + = check_box_tag nil, nil, nil, { "data-action": "change->select-all#toggleAll", "data-select-all-target": "all" } + = t(".select_all") + %td + %em= distributor.name + - distributor_payment_methods.each do |distributor_payment_method| + %p + %label{ class: ("disabled" if distributor_payment_methods.one? || !distributor_payment_method.payment_method.frontend?) } + = check_box_tag "order_cycle[selected_distributor_payment_method_ids][]", + distributor_payment_method.id, + @order_cycle.distributor_payment_methods.include?(distributor_payment_method), + id: "order_cycle_selected_distributor_payment_method_ids_#{distributor_payment_method.id}", + data: ({ "action" => "change->select-all#toggleCheckbox", "select-all-target" => "checkbox" } if distributor_payment_method.payment_method.frontend?) + = distributor_payment_method.payment_method.name + - distributor.payment_methods.inactive_or_backend.each do |payment_method| + %label.disabled + = check_box_tag nil, nil, false, disabled: true + = payment_method.name + = "(#{t('.back_end')})" + - if distributor.payment_methods.available.none? + %p + = t('.no_payment_methods') %div#save-bar %div.container diff --git a/lib/open_food_network/available_payment_method_filter.rb b/lib/open_food_network/available_payment_method_filter.rb deleted file mode 100644 index 4afbfa94d5..0000000000 --- a/lib/open_food_network/available_payment_method_filter.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -module OpenFoodNetwork - class AvailablePaymentMethodFilter - def filter!(payment_methods) - if stripe_enabled? - payment_methods.to_a.reject! do |payment_method| - payment_method.type.ends_with?("StripeSCA") && - stripe_configuration_incomplete?(payment_method) - end - else - payment_methods.to_a.reject! do |payment_method| - payment_method.type.ends_with?("StripeSCA") - end - end - end - - private - - def stripe_enabled? - Spree::Config.stripe_connect_enabled && Stripe.publishable_key - end - - def stripe_configuration_incomplete?(payment_method) - payment_method.preferred_enterprise_id.nil? || - payment_method.preferred_enterprise_id.zero? || - payment_method.stripe_account_id.blank? - end - end -end diff --git a/spec/helpers/enterprises_helper_spec.rb b/spec/helpers/enterprises_helper_spec.rb deleted file mode 100644 index 9bea500126..0000000000 --- a/spec/helpers/enterprises_helper_spec.rb +++ /dev/null @@ -1,175 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe EnterprisesHelper, type: :helper do - let(:user) { create(:user) } - let(:distributor) { create(:distributor_enterprise) } - let(:some_other_distributor) { create(:distributor_enterprise) } - - before { allow(helper).to receive(:spree_current_user) { user } } - - describe "loading available payment methods" do - let!(:pm1) { create(:payment_method, distributors: [distributor]) } - let!(:pm2) { create(:payment_method, distributors: [some_other_distributor]) } - - context "when the order has no current_distributor" do - before do - allow(helper).to receive(:current_distributor) { nil } - end - - it "returns an empty array" do - expect(helper.available_payment_methods).to eq [] - end - end - - context "when no tag rules are in effect" do - before { allow(helper).to receive(:current_distributor) { distributor } } - - it "finds the payment methods for the current distributor" do - expect(helper.available_payment_methods).to_not include pm2 - expect(helper.available_payment_methods).to include pm1 - end - end - - context "when FilterPaymentMethods tag rules are in effect" do - let(:customer) { create(:customer, user: user, enterprise: distributor) } - let!(:tag_rule) { - create(:filter_payment_methods_tag_rule, - enterprise: distributor, - preferred_customer_tags: "trusted", - preferred_payment_method_tags: "trusted") - } - let!(:default_tag_rule) { - create(:filter_payment_methods_tag_rule, - enterprise: distributor, - is_default: true, - preferred_payment_method_tags: "trusted") - } - let(:tagged_pm) { pm1 } - let(:untagged_pm) { pm2 } - - before do - tagged_pm.update_attribute(:tag_list, 'trusted') - distributor.payment_methods = [tagged_pm, untagged_pm] - allow(helper).to receive(:current_distributor) { distributor } - end - - context "with a preferred visiblity of 'visible', default visibility of 'hidden'" do - before { - tag_rule.update_attribute(:preferred_matched_payment_methods_visibility, 'visible') - } - before { - default_tag_rule.update_attribute(:preferred_matched_payment_methods_visibility, 'hidden') - } - - context "when the customer is nil" do - it "applies default action (hide)" do - expect(helper.current_customer).to be nil - expect(helper.available_payment_methods).to include untagged_pm - expect(helper.available_payment_methods).to_not include tagged_pm - end - end - - context "when the customer's tags match" do - before { customer.update_attribute(:tag_list, 'trusted') } - - it "applies the action (show)" do - expect(helper.current_customer).to eq customer - expect(helper.available_payment_methods).to include tagged_pm, untagged_pm - end - end - - context "when the customer's tags don't match" do - before { customer.update_attribute(:tag_list, 'something') } - - it "applies the default action (hide)" do - expect(helper.current_customer).to eq customer - expect(helper.available_payment_methods).to include untagged_pm - expect(helper.available_payment_methods).to_not include tagged_pm - end - end - end - - context "with a preferred visiblity of 'hidden', default visibility of 'visible'" do - before { - tag_rule.update_attribute(:preferred_matched_payment_methods_visibility, 'hidden') - } - before { - default_tag_rule.update_attribute(:preferred_matched_payment_methods_visibility, - 'visible') - } - - context "when the customer is nil" do - it "applies default action (show)" do - expect(helper.current_customer).to be nil - expect(helper.available_payment_methods).to include tagged_pm, untagged_pm - end - end - - context "when the customer's tags match" do - before { customer.update_attribute(:tag_list, 'trusted') } - - it "applies the action (hide)" do - expect(helper.current_customer).to eq customer - expect(helper.available_payment_methods).to include untagged_pm - expect(helper.available_payment_methods).to_not include tagged_pm - end - end - - context "when the customer's tags don't match" do - before { customer.update_attribute(:tag_list, 'something') } - - it "applies the default action (show)" do - expect(helper.current_customer).to eq customer - expect(helper.available_payment_methods).to include tagged_pm, untagged_pm - end - end - end - end - - context "when Stripe payment methods are present" do - let!(:pm3) { - create(:stripe_sca_payment_method, distributors: [distributor], - preferred_enterprise_id: distributor.id) - } - let!(:pm4) { - create(:stripe_sca_payment_method, distributors: [distributor], - preferred_enterprise_id: some_other_distributor.id) - } - let(:available_payment_methods) { helper.available_payment_methods } - - around do |example| - original_stripe_connect_enabled = Spree::Config[:stripe_connect_enabled] - example.run - Spree::Config.set(stripe_connect_enabled: original_stripe_connect_enabled) - end - - before do - allow(helper).to receive(:current_distributor) { distributor } - end - - context "and Stripe Connect is disabled" do - before { Spree::Config.set(stripe_connect_enabled: false) } - - it "ignores Stripe payment methods" do - expect(available_payment_methods).to_not include pm3, pm4 - end - end - - context "and Stripe Connect is enabled" do - let!(:stripe_account) { create(:stripe_account, enterprise_id: distributor.id) } - - before do - Spree::Config.set(stripe_connect_enabled: true) - Stripe.publishable_key = "some_key" - end - - it "includes Stripe payment methods with a valid stripe accounts" do - expect(available_payment_methods).to include pm3 - expect(available_payment_methods).to_not include pm4 - end - end - end - end -end diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb index e5892cd1e6..7a0df9afda 100644 --- a/spec/models/enterprise_spec.rb +++ b/spec/models/enterprise_spec.rb @@ -276,7 +276,7 @@ describe Enterprise do expect(Enterprise.ready_for_checkout).not_to include e end - it "does not show enterprises wchich only have backend shipping methods" do + it "does not show enterprises which only have backend shipping methods" do create(:shipping_method, distributors: [e], display_on: Spree::ShippingMethod::DISPLAY_ON_OPTIONS[:back_end]) create(:payment_method, distributors: [e]) @@ -354,6 +354,13 @@ describe Enterprise do create(:payment_method, distributors: [e]) expect(e.reload).to be_ready_for_checkout end + + it "returns false for enterprises with payment methods that are available but not configured + correctly" do + create(:shipping_method, distributors: [e]) + create(:stripe_sca_payment_method, distributors: [e]) + expect(e.reload).not_to be_ready_for_checkout + end end describe "distributors_with_active_order_cycles" do diff --git a/spec/models/order_cycle_spec.rb b/spec/models/order_cycle_spec.rb index 3789a4aa1a..a890d68e9a 100644 --- a/spec/models/order_cycle_spec.rb +++ b/spec/models/order_cycle_spec.rb @@ -404,7 +404,32 @@ describe OrderCycle do expect(cloned_exchange_attributes).to match_array original_exchange_attributes end - context "when it has preferred shipping methods which can longer be applied validly + context "when it has selected payment methods which can longer be applied validly + e.g. payment method is backoffice only" do + it "only attaches the valid ones to the clone" do + distributor = create(:distributor_enterprise) + distributor_payment_method_i = create( + :payment_method, + distributors: [distributor] + ).distributor_payment_methods.first + distributor_payment_method_ii = create( + :payment_method, + distributors: [distributor], + display_on: "back_end" + ).distributor_payment_methods.first + order_cycle = create(:distributor_order_cycle, distributors: [distributor]) + order_cycle.selected_distributor_payment_methods = [ + distributor_payment_method_i, + distributor_payment_method_ii + ] + + cloned_order_cycle = order_cycle.clone! + + expect(cloned_order_cycle.distributor_payment_methods).to eq [distributor_payment_method_i] + end + end + + context "when it has selected shipping methods which can longer be applied validly e.g. shipping method is backoffice only" do it "only attaches the valid ones to the clone" do distributor = create(:distributor_enterprise) @@ -637,6 +662,32 @@ describe OrderCycle do end end + describe "#attachable_distributor_payment_methods" do + it "includes distributor payment methods from the distributors on the order cycle" do + payment_method = create(:payment_method) + oc = create(:simple_order_cycle, distributors: [payment_method.distributors.first]) + distributor_payment_method = payment_method.distributor_payment_methods.first + + expect(oc.attachable_distributor_payment_methods).to eq([distributor_payment_method]) + end + + it "does not include backoffice only distributor payment methods" do + payment_method = create(:payment_method, display_on: "back_end") + enterprise = create(:enterprise, payment_methods: [payment_method]) + oc = create(:simple_order_cycle, distributors: [enterprise]) + + expect(oc.attachable_distributor_payment_methods).to be_empty + end + + it "does not include inactive distributor payment methods" do + payment_method = create(:payment_method, active: false) + enterprise = create(:enterprise, payment_methods: [payment_method]) + oc = create(:simple_order_cycle, distributors: [enterprise]) + + expect(oc.attachable_distributor_payment_methods).to be_empty + end + end + describe "#attachable_distributor_shipping_methods" do it "includes distributor shipping methods from the distributors on the order cycle" do shipping_method = create(:shipping_method) @@ -655,6 +706,80 @@ describe OrderCycle do end end + describe "#distributor_payment_methods" do + let(:distributor) { create(:distributor_enterprise) } + + it "returns all attachable distributor payment methods if the order cycle is simple" do + oc = create(:sells_own_order_cycle, distributors: [distributor]) + + distributor_payment_method = create( + :payment_method, + distributors: [distributor] + ).distributor_payment_methods.first + + expect(oc.distributor_payment_methods).to eq [distributor_payment_method] + end + + context "distributor order cycle i.e. non-simple" do + let(:oc) { create(:distributor_order_cycle, distributors: [distributor]) } + + it "returns all attachable distributor payment methods if no distributor payment methods + have been selected specifically" do + distributor_payment_method = create( + :payment_method, + distributors: [distributor] + ).distributor_payment_methods.first + + expect(oc.selected_distributor_payment_methods).to be_empty + expect(oc.distributor_payment_methods).to eq [distributor_payment_method] + end + + it "returns selected distributor payment methods if they have been specified" do + distributor_payment_method_i = create( + :payment_method, + distributors: [distributor] + ).distributor_payment_methods.first + distributor_payment_method_ii = create( + :payment_method, + distributors: [distributor] + ).distributor_payment_methods.first + + oc.selected_distributor_payment_methods << distributor_payment_method_ii + + expect(oc.distributor_payment_methods).to eq [distributor_payment_method_ii] + end + + context "with multiple distributors" do + let(:other_distributor) { create(:distributor_enterprise) } + let(:oc) { create(:distributor_order_cycle, distributors: [distributor, other_distributor]) } + + it "returns all attachable distributor payment methods for a distributor if no distributor + payment methods have been selected specifically for that distributor, even if + distributor payment methods have been selected specifically for a different distributor + on the order cycle" do + distributor_payment_method = create( + :payment_method, + distributors: [distributor] + ).distributor_payment_methods.first + other_distributor_payment_method_i = create( + :payment_method, + distributors: [other_distributor] + ).distributor_payment_methods.first + other_distributor_payment_method_ii = create( + :payment_method, + distributors: [other_distributor] + ).distributor_payment_methods.first + oc.selected_distributor_payment_methods << other_distributor_payment_method_i + + expect(oc.distributor_payment_methods).to eq [ + distributor_payment_method, + other_distributor_payment_method_i + ] + end + end + end + end + describe "#distributor_shipping_methods" do let(:distributor) { create(:distributor_enterprise) } diff --git a/spec/models/spree/payment_method_spec.rb b/spec/models/spree/payment_method_spec.rb index e32548a966..69554ff462 100644 --- a/spec/models/spree/payment_method_spec.rb +++ b/spec/models/spree/payment_method_spec.rb @@ -5,100 +5,166 @@ require 'spec_helper' class Spree::Gateway::Test < Spree::Gateway end -module Spree - describe PaymentMethod do - describe "#available" do - let(:enterprise) { create(:enterprise) } +describe Spree::PaymentMethod do + describe "#available" do + let(:enterprise) { create(:enterprise) } + + before do + Spree::PaymentMethod.delete_all + + [nil, 'both', 'back_end'].each do |display_on| + Spree::Gateway::Test.create( + name: 'Display Both', + display_on: display_on, + active: true, + environment: 'test', + description: 'foofah', + distributors: [enterprise] + ) + end + expect(Spree::PaymentMethod.all.size).to eq 3 + end + + it "should return all methods available to front-end/back-end when no parameter is passed" do + expect(Spree::PaymentMethod.available.size).to eq 2 + end + + it "should return all methods available to front-end/back-end when display_on = :both" do + expect(Spree::PaymentMethod.available(:both).size).to eq 2 + end + + it "should return all methods available to back-end when display_on = :back_end" do + expect(Spree::PaymentMethod.available(:back_end).size).to eq 2 + end + end + + describe "#configured?" do + context "non-Stripe payment method" do + let(:payment_method) { build(:payment_method) } + + it "returns true" do + expect(payment_method).to be_configured + end + end + + context "Stripe payment method" do + let(:payment_method) { create(:stripe_sca_payment_method) } + + around do |example| + original_stripe_connect_enabled = Spree::Config[:stripe_connect_enabled] + example.run + Spree::Config.set(stripe_connect_enabled: original_stripe_connect_enabled) + end before do - Spree::PaymentMethod.delete_all + Spree::Config.set(stripe_connect_enabled: true) + Stripe.publishable_key = "some_key" + end - [nil, 'both', 'back_end'].each do |display_on| - Spree::Gateway::Test.create( - name: 'Display Both', - display_on: display_on, - active: true, - environment: 'test', - description: 'foofah', - distributors: [enterprise] - ) + context "and Stripe Connect is enabled and a Stripe publishable key, account id, account + owner are all present" do + it "returns true" do + expect(payment_method).to be_configured end - expect(Spree::PaymentMethod.all.size).to eq 3 end - it "should return all methods available to front-end/back-end when no parameter is passed" do - expect(Spree::PaymentMethod.available.size).to eq 2 + context "and Stripe Connect is disabled" do + before { Spree::Config.set(stripe_connect_enabled: false) } + + it "returns false" do + expect(payment_method).not_to be_configured + end end - it "should return all methods available to front-end/back-end when display_on = :both" do - expect(Spree::PaymentMethod.available(:both).size).to eq 2 + context "and a Stripe publishable key is not present" do + before { Spree::Config.set(stripe_connect_enabled: false) } + + it "returns false" do + expect(payment_method).not_to be_configured + end end - it "should return all methods available to back-end when display_on = :back_end" do - expect(Spree::PaymentMethod.available(:back_end).size).to eq 2 + context "and a Stripe account owner is not present" do + before { payment_method.preferred_enterprise_id = nil } + + it "returns false" do + expect(payment_method).not_to be_configured + end end - end - it "orders payment methods by name" do - pm1 = create(:payment_method, name: 'ZZ') - pm2 = create(:payment_method, name: 'AA') - pm3 = create(:payment_method, name: 'BB') + context "and a Stripe account ID is not present" do + before do + StripeAccount.find_by( + enterprise_id: payment_method.preferred_enterprise_id + ).update_column(:stripe_user_id, nil) + end - expect(PaymentMethod.by_name).to eq([pm2, pm3, pm1]) - end - - it "raises errors when required fields are missing" do - pm = PaymentMethod.new - pm.save - expect(pm.errors.to_a).to eq(["Name can't be blank", "At least one hub must be selected"]) - end - - it "generates a clean name for known Payment Method types" do - expect(Spree::PaymentMethod::Check.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.check")) - expect(Spree::Gateway::PayPalExpress.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.paypalexpress")) - expect(Spree::Gateway::StripeSCA.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.stripesca")) - expect(Spree::Gateway::BogusSimple.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.bogussimple")) - expect(Spree::Gateway::Bogus.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.bogus")) - end - - it "computes the amount of fees" do - order = create(:order) - - free_payment_method = create(:payment_method) # flat rate calculator with preferred_amount of 0 - expect(free_payment_method.compute_amount(order)).to eq 0 - - flat_rate_payment_method = create(:payment_method, - calculator: ::Calculator::FlatRate.new(preferred_amount: 10)) - expect(flat_rate_payment_method.compute_amount(order)).to eq 10 - - flat_percent_payment_method = create(:payment_method, - calculator: ::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10)) - expect(flat_percent_payment_method.compute_amount(order)).to eq 0 - - product = create(:product) - order.contents.add(product.variants.first) - expect(flat_percent_payment_method.compute_amount(order)).to eq 2.0 - end - - describe "scope" do - describe "filtering to specified distributors" do - let!(:distributor_a) { create(:distributor_enterprise) } - let!(:distributor_b) { create(:distributor_enterprise) } - let!(:distributor_c) { create(:distributor_enterprise) } - - let!(:payment_method_a) { - create(:payment_method, distributors: [distributor_a, distributor_b]) - } - let!(:payment_method_b) { create(:payment_method, distributors: [distributor_b]) } - let!(:payment_method_c) { create(:payment_method, distributors: [distributor_c]) } - - it "includes only unique records under specified distributors" do - result = described_class.for_distributors([distributor_a, distributor_b]) - expect(result.length).to eq(2) - expect(result).to include(payment_method_a) - expect(result).to include(payment_method_b) + it "returns false" do + expect(payment_method).not_to be_configured end end end end + + it "orders payment methods by name" do + pm1 = create(:payment_method, name: 'ZZ') + pm2 = create(:payment_method, name: 'AA') + pm3 = create(:payment_method, name: 'BB') + + expect(Spree::PaymentMethod.by_name).to eq([pm2, pm3, pm1]) + end + + it "raises errors when required fields are missing" do + pm = Spree::PaymentMethod.new + pm.save + expect(pm.errors.to_a).to eq(["Name can't be blank", "At least one hub must be selected"]) + end + + it "generates a clean name for known Payment Method types" do + expect(Spree::PaymentMethod::Check.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.check")) + expect(Spree::Gateway::PayPalExpress.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.paypalexpress")) + expect(Spree::Gateway::StripeSCA.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.stripesca")) + expect(Spree::Gateway::BogusSimple.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.bogussimple")) + expect(Spree::Gateway::Bogus.clean_name).to eq(I18n.t("spree.admin.payment_methods.providers.bogus")) + end + + it "computes the amount of fees" do + order = create(:order) + + free_payment_method = create(:payment_method) # flat rate calculator with preferred_amount of 0 + expect(free_payment_method.compute_amount(order)).to eq 0 + + flat_rate_payment_method = create(:payment_method, + calculator: ::Calculator::FlatRate.new(preferred_amount: 10)) + expect(flat_rate_payment_method.compute_amount(order)).to eq 10 + + flat_percent_payment_method = create(:payment_method, + calculator: ::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10)) + expect(flat_percent_payment_method.compute_amount(order)).to eq 0 + + product = create(:product) + order.contents.add(product.variants.first) + expect(flat_percent_payment_method.compute_amount(order)).to eq 2.0 + end + + describe "scope" do + describe "filtering to specified distributors" do + let!(:distributor_a) { create(:distributor_enterprise) } + let!(:distributor_b) { create(:distributor_enterprise) } + let!(:distributor_c) { create(:distributor_enterprise) } + + let!(:payment_method_a) { + create(:payment_method, distributors: [distributor_a, distributor_b]) + } + let!(:payment_method_b) { create(:payment_method, distributors: [distributor_b]) } + let!(:payment_method_c) { create(:payment_method, distributors: [distributor_c]) } + + it "includes only unique records under specified distributors" do + result = described_class.for_distributors([distributor_a, distributor_b]) + expect(result.length).to eq(2) + expect(result).to include(payment_method_a) + expect(result).to include(payment_method_b) + end + end + end end diff --git a/spec/requests/checkout/stripe_sca_spec.rb b/spec/requests/checkout/stripe_sca_spec.rb index 586897b828..0c806e40d4 100644 --- a/spec/requests/checkout/stripe_sca_spec.rb +++ b/spec/requests/checkout/stripe_sca_spec.rb @@ -82,11 +82,18 @@ describe "checking out an order with a Stripe SCA payment method", type: :reques } end + around do |example| + original_stripe_connect_enabled = Spree::Config[:stripe_connect_enabled] + example.run + Spree::Config.set(stripe_connect_enabled: original_stripe_connect_enabled) + end + before do order_cycle_distributed_variants = double(:order_cycle_distributed_variants) allow(OrderCycleDistributedVariants).to receive(:new) { order_cycle_distributed_variants } allow(order_cycle_distributed_variants).to receive(:distributes_order_variants?) { true } - + allow(Stripe).to receive(:publishable_key).and_return("some_token") + Spree::Config.set(stripe_connect_enabled: true) Stripe.api_key = "sk_test_12345" order.update(distributor_id: enterprise.id, order_cycle_id: order_cycle.id) order.reload.update_totals diff --git a/spec/services/order_available_payment_methods_spec.rb b/spec/services/order_available_payment_methods_spec.rb new file mode 100644 index 0000000000..a8e4fedb45 --- /dev/null +++ b/spec/services/order_available_payment_methods_spec.rb @@ -0,0 +1,217 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe OrderAvailablePaymentMethods do + context "when the order has no current_distributor" do + it "returns an empty array" do + order_cycle = create(:sells_own_order_cycle) + order = build(:order, distributor: nil, order_cycle: order_cycle) + + expect(OrderAvailablePaymentMethods.new(order).to_a).to eq [] + end + end + + it "does not return 'back office only' payment method" do + distributor = create(:distributor_enterprise) + frontend_payment_method = create(:payment_method, distributors: [distributor]) + backoffice_only_payment_method = create(:payment_method, + distributors: [distributor], + display_on: 'back_end') + order_cycle = create(:sells_own_order_cycle) + order = build(:order, distributor: distributor, order_cycle: order_cycle) + + available_payment_methods = OrderAvailablePaymentMethods.new(order).to_a + + expect(available_payment_methods).to eq [frontend_payment_method] + end + + it "does not return payment methods which are not configured correctly" do + distributor = create(:distributor_enterprise) + frontend_payment_method = create(:payment_method, distributors: [distributor]) + unconfigured_payment_method = create(:stripe_sca_payment_method, + distributors: [distributor], + display_on: 'back_end') + order_cycle = create(:sells_own_order_cycle) + order = build(:order, distributor: distributor, order_cycle: order_cycle) + + available_payment_methods = OrderAvailablePaymentMethods.new(order).to_a + + expect(available_payment_methods).to eq [frontend_payment_method] + end + + context "when no tag rules are in effect" do + context "sells own order cycle i.e. simple" do + it "only returns the payment methods which are available on the order cycle + and belong to the order distributor" do + distributor_i = create(:distributor_enterprise) + distributor_ii = create(:distributor_enterprise) + distributor_iii = create(:distributor_enterprise) + payment_method_i = create(:payment_method, distributors: [distributor_i]) + payment_method_ii = create(:payment_method, distributors: [distributor_ii]) + payment_method_iii = create(:payment_method, distributors: [distributor_iii]) + order_cycle = create(:sells_own_order_cycle, distributors: [distributor_i, distributor_ii]) + order = build(:order, distributor: distributor_i, order_cycle: order_cycle) + + available_payment_methods = OrderAvailablePaymentMethods.new(order).to_a + + expect(available_payment_methods).to eq [payment_method_i] + end + end + + context "distributor order cycle i.e. not simple" do + it "only returns the payment methods which are available on the order cycle + and belong to the order distributor" do + distributor_i = create(:distributor_enterprise, payment_methods: []) + distributor_ii = create(:distributor_enterprise, payment_methods: []) + payment_method_i = create(:payment_method, distributors: [distributor_i]) + payment_method_ii = create(:payment_method, distributors: [distributor_i]) + payment_method_iii = create(:payment_method, distributors: [distributor_ii]) + payment_method_iv = create(:payment_method, distributors: [distributor_ii]) + order_cycle = create(:distributor_order_cycle, + distributors: [distributor_i, distributor_ii]) + order_cycle.selected_distributor_payment_methods << [ + distributor_i.distributor_payment_methods.first, + distributor_ii.distributor_payment_methods.first, + ] + order = build(:order, distributor: distributor_i, order_cycle: order_cycle) + + available_payment_methods = OrderAvailablePaymentMethods.new(order).to_a + + expect(available_payment_methods).to eq [payment_method_i] + end + end + end + + context "when FilterPaymentMethods tag rules are in effect" do + let(:user) { create(:user) } + let(:distributor) { create(:distributor_enterprise) } + let(:other_distributor) { create(:distributor_enterprise) } + let!(:distributor_payment_method) { create(:payment_method, distributors: [distributor]) } + let!(:other_distributor_payment_method) do + create(:payment_method, distributors: [other_distributor]) + end + let(:customer) { create(:customer, user: user, enterprise: distributor) } + let!(:tag_rule) { + create(:filter_payment_methods_tag_rule, + enterprise: distributor, + preferred_customer_tags: "local", + preferred_payment_method_tags: "local-delivery") + } + let!(:default_tag_rule) { + create(:filter_payment_methods_tag_rule, + enterprise: distributor, + is_default: true, + preferred_payment_method_tags: "local-delivery") + } + let!(:tagged_payment_method) { distributor_payment_method } + let!(:untagged_payment_method) { other_distributor_payment_method } + + before do + tagged_payment_method.update_attribute(:tag_list, 'local-delivery') + distributor.payment_methods = [tagged_payment_method, untagged_payment_method] + end + + context "with a preferred visiblity of 'visible', default visibility of 'hidden'" do + before { + tag_rule.update_attribute(:preferred_matched_payment_methods_visibility, 'visible') + } + before { + default_tag_rule.update_attribute(:preferred_matched_payment_methods_visibility, + 'hidden') + } + + let(:order_cycle) { create(:sells_own_order_cycle) } + let(:order) { build(:order, distributor: distributor, order_cycle: order_cycle) } + + context "when the customer is nil" do + let(:available_payment_methods) { OrderAvailablePaymentMethods.new(order).to_a } + + it "applies default action (hide)" do + expect(available_payment_methods).to include untagged_payment_method + expect(available_payment_methods).to_not include tagged_payment_method + end + end + + context "when a customer is present" do + let(:available_payment_methods) { OrderAvailablePaymentMethods.new(order, customer).to_a } + + context "and the customer's tags match" do + before do + customer.update_attribute(:tag_list, 'local') + end + + it "applies the action (show)" do + expect(available_payment_methods).to include( + tagged_payment_method, + untagged_payment_method + ) + end + end + + context "and the customer's tags don't match" do + before do + customer.update_attribute(:tag_list, 'something') + end + + it "applies the default action (hide)" do + expect(available_payment_methods).to include untagged_payment_method + expect(available_payment_methods).to_not include tagged_payment_method + end + end + end + end + + context "with a preferred visiblity of 'hidden', default visibility of 'visible'" do + before { + tag_rule.update_attribute(:preferred_matched_payment_methods_visibility, 'hidden') + } + before { + default_tag_rule.update_attribute(:preferred_matched_payment_methods_visibility, + 'visible') + } + + let(:order_cycle) { create(:sells_own_order_cycle) } + let(:order) { build(:order, distributor: distributor, order_cycle: order_cycle) } + + context "when the customer is nil" do + let(:available_payment_methods) { OrderAvailablePaymentMethods.new(order).to_a } + + it "applies default action (show)" do + expect(available_payment_methods).to include( + tagged_payment_method, + untagged_payment_method + ) + end + end + + context "when a customer is present" do + let(:available_payment_methods) { OrderAvailablePaymentMethods.new(order, customer).to_a } + + context "and the customer's tags match" do + before do + customer.update_attribute(:tag_list, 'local') + end + + it "applies the action (hide)" do + expect(available_payment_methods).to include untagged_payment_method + expect(available_payment_methods).to_not include tagged_payment_method + end + end + + context "and the customer's tags don't match" do + before do + customer.update_attribute(:tag_list, 'something') + end + + it "applies the default action (show)" do + expect(available_payment_methods).to include( + tagged_payment_method, + untagged_payment_method + ) + end + end + end + end + end +end diff --git a/spec/services/order_cycle_form_spec.rb b/spec/services/order_cycle_form_spec.rb index 0117a1537a..a9ed405458 100644 --- a/spec/services/order_cycle_form_spec.rb +++ b/spec/services/order_cycle_form_spec.rb @@ -135,7 +135,9 @@ describe OrderCycleForm do let(:distributor) { order_cycle.coordinator } let(:supplier) { create(:supplier_enterprise) } let(:user) { distributor.owner } + let(:payment_method) { create(:payment_method, distributors: [distributor]) } let(:shipping_method) { create(:shipping_method, distributors: [distributor]) } + let(:distributor_payment_method) { payment_method.distributor_payment_methods.first } let(:distributor_shipping_method) { shipping_method.distributor_shipping_methods.first } let(:variant) { create(:variant, product: create(:product, supplier: supplier)) } let(:params) { { name: 'Some new name' } } @@ -151,14 +153,14 @@ describe OrderCycleForm do } end - context "basic update i.e. without exchanges or shipping methods" do + context "basic update i.e. without exchanges or payment/shipping methods" do it do expect(form.save).to be true expect(order_cycle.name).to eq 'Some new name' end end - context "updating basics, incoming exchanges, outcoming exchanges + context "updating basics, incoming exchanges, outcoming exchanges, payment_methods and shipping methods simultaneously" do before do params.merge!( @@ -171,21 +173,31 @@ describe OrderCycleForm do enterprise_fee_ids: [] }], outgoing_exchanges: [outgoing_exchange_params], + selected_distributor_payment_method_ids: [distributor_payment_method.id], selected_distributor_shipping_method_ids: [distributor_shipping_method.id] ) end - it "saves everything i.e. the basics, incoming and outgoing exchanges and shipping methods" do + it "saves everything i.e. the basics, incoming and outgoing exchanges, payment methods and + shipping methods" do expect(form.save).to be true expect(order_cycle.name).to eq 'Some new name' expect(order_cycle.cached_incoming_exchanges.count).to eq 1 expect(order_cycle.cached_outgoing_exchanges.count).to eq 1 + expect(order_cycle.distributor_payment_methods).to eq [distributor_payment_method] expect(order_cycle.distributor_shipping_methods).to eq [distributor_shipping_method] end end - context "updating outgoing exchanges and shipping methods simultaneously but the shipping - method doesn't belong to the new or any existing order cycle distributor" do + context "updating outgoing exchanges and shipping methods simultaneously but the payment + and shipping methods don't belong to the new or any existing order cycle + distributor" do + let(:other_distributor_payment_method) do + create( + :payment_method, + distributors: [create(:distributor_enterprise)] + ).distributor_payment_methods.first + end let(:other_distributor_shipping_method) do create( :shipping_method, @@ -196,6 +208,7 @@ describe OrderCycleForm do before do params.merge!( outgoing_exchanges: [outgoing_exchange_params], + selected_distributor_payment_method_ids: [other_distributor_payment_method.id], selected_distributor_shipping_method_ids: [other_distributor_shipping_method.id] ) end @@ -203,10 +216,59 @@ describe OrderCycleForm do it "saves the outgoing exchange but ignores the shipping method" do expect(form.save).to be true expect(order_cycle.distributors).to eq [distributor] + expect(order_cycle.distributor_payment_methods).to be_empty expect(order_cycle.distributor_shipping_methods).to be_empty end end + context "updating payment methods" do + context "and it's valid" do + it "saves the changes" do + distributor = create(:distributor_enterprise) + distributor_payment_method = create( + :payment_method, + distributors: [distributor] + ).distributor_payment_methods.first + order_cycle = create(:distributor_order_cycle, distributors: [distributor]) + + form = OrderCycleForm.new( + order_cycle, + { selected_distributor_payment_method_ids: [distributor_payment_method.id] }, + order_cycle.coordinator + ) + + expect(form.save).to be true + expect(order_cycle.distributor_payment_methods).to eq [distributor_payment_method] + end + end + + context "with a payment method which doesn't belong to any distributor on the order cycle" do + it "ignores it" do + distributor_i = create(:distributor_enterprise) + distributor_ii = create(:distributor_enterprise) + distributor_payment_method_i = create( + :payment_method, + distributors: [distributor_i] + ).distributor_payment_methods.first + distributor_payment_method_ii = create( + :payment_method, + distributors: [distributor_ii] + ).distributor_payment_methods.first + order_cycle = create(:distributor_order_cycle, + distributors: [distributor_i]) + + form = OrderCycleForm.new( + order_cycle, + { selected_distributor_payment_method_ids: [distributor_payment_method_ii.id] }, + order_cycle.coordinator + ) + + expect(form.save).to be true + expect(order_cycle.distributor_payment_methods).to eq [distributor_payment_method_i] + end + end + end + context "updating shipping methods" do context "and it's valid" do it "saves the changes" do diff --git a/spec/system/admin/order_cycles/complex_creating_specific_time_spec.rb b/spec/system/admin/order_cycles/complex_creating_specific_time_spec.rb index 4654b12109..90e388e847 100644 --- a/spec/system/admin/order_cycles/complex_creating_specific_time_spec.rb +++ b/spec/system/admin/order_cycles/complex_creating_specific_time_spec.rb @@ -22,6 +22,8 @@ describe ' let!(:distributor) { create(:distributor_enterprise, name: 'My distributor', with_payment_and_shipping: true) } + let!(:payment_method_i) { distributor.payment_methods.first } + let!(:payment_method_ii) { create(:payment_method, distributors: [distributor]) } let!(:shipping_method_i) { distributor.shipping_methods.first } let!(:shipping_method_ii) { create(:shipping_method, distributors: [distributor]) } let(:oc) { OrderCycle.last } @@ -44,6 +46,7 @@ describe ' shipping_method_i.update!(name: "Pickup - always available") shipping_method_ii.update!(name: "Delivery - sometimes available") + payment_method_ii.update!(name: "Cash") end it "creating an order cycle with full interface", js: true do @@ -68,6 +71,8 @@ describe ' add_supplier_with_fees add_distributor_with_fees select_distributor_shipping_methods + select_distributor_payment_methods + click_button 'Save and Back to List' expect_all_data_saved end @@ -161,22 +166,50 @@ describe ' click_button 'Save and Next' end + def select_distributor_payment_methods + within("tr.distributor-#{distributor.id}-payment-methods") do + expect(page).to have_checked_field "Select all" + + expect(page).to have_checked_field "Check" + expect(page).to have_checked_field "Cash" + + uncheck "Cash" + + expect(page).to have_unchecked_field "Select all" + + expect_checking_select_all_payment_methods_works + expect_unchecking_select_all_payment_methods_works + + # Our final selection: + check "Check" + end + end + def select_distributor_shipping_methods - expect(page).to have_checked_field "Select all" + within("tr.distributor-#{distributor.id}-shipping-methods") do + expect(page).to have_checked_field "Select all" - expect(page).to have_checked_field "Pickup - always available" - expect(page).to have_checked_field "Delivery - sometimes available" + expect(page).to have_checked_field "Pickup - always available" + expect(page).to have_checked_field "Delivery - sometimes available" - uncheck "Delivery - sometimes available" + uncheck "Delivery - sometimes available" - expect(page).to have_unchecked_field "Select all" + expect(page).to have_unchecked_field "Select all" - expect_checking_select_all_shipping_methods_works - expect_unchecking_select_all_shipping_methods_works + expect_checking_select_all_shipping_methods_works + expect_unchecking_select_all_shipping_methods_works - # Our final selection: - check "Pickup - always available" - click_button 'Save and Back to List' + # Our final selection: + check "Pickup - always available" + end + end + + def expect_checking_select_all_payment_methods_works + # Now test that the "Select all" input is doing what it's supposed to: + check "Select all" + + expect(page).to have_checked_field "Check" + expect(page).to have_checked_field "Cash" end def expect_checking_select_all_shipping_methods_works @@ -187,6 +220,13 @@ describe ' expect(page).to have_checked_field "Delivery - sometimes available" end + def expect_unchecking_select_all_payment_methods_works + uncheck "Select all" + + expect(page).to have_unchecked_field "Check" + expect(page).to have_unchecked_field "Cash" + end + def expect_unchecking_select_all_shipping_methods_works uncheck "Select all" @@ -208,6 +248,7 @@ describe ' expect_receival_instructions_saved expect_pickup_time_and_instructions_saved expect_distributor_shipping_methods_saved + expect_distributor_payment_methods_saved end def expect_opening_and_closing_times_saved @@ -240,6 +281,10 @@ describe ' expect(exchange.tag_list).to eq(['wholesale']) end + def expect_distributor_payment_methods_saved + expect(oc.distributor_payment_methods).to eq(payment_method_i.distributor_payment_methods) + end + def expect_distributor_shipping_methods_saved expect(oc.distributor_shipping_methods).to eq(shipping_method_i.distributor_shipping_methods) end diff --git a/spec/system/admin/order_cycles/simple_spec.rb b/spec/system/admin/order_cycles/simple_spec.rb index 91954611ff..770a7a16bc 100644 --- a/spec/system/admin/order_cycles/simple_spec.rb +++ b/spec/system/admin/order_cycles/simple_spec.rb @@ -272,6 +272,8 @@ describe ' expect_shipping_methods_to_be_checked_for(distributor_managed) expect_shipping_methods_to_be_checked_for(distributor_permitted) + expect_payment_methods_to_be_checked_for(distributor_managed) + expect_payment_methods_to_be_checked_for(distributor_permitted) click_button 'Save and Back to List' order_cycle = OrderCycle.find_by(name: 'My order cycle') @@ -286,6 +288,9 @@ describe ' expect(order_cycle.distributor_shipping_methods).to match_array( order_cycle.attachable_distributor_shipping_methods ) + expect(order_cycle.distributor_payment_methods).to match_array( + order_cycle.attachable_distributor_payment_methods + ) end context "editing an order cycle" do @@ -724,6 +729,14 @@ describe ' private + def expect_payment_methods_to_be_checked_for(distributor) + distributor.distributor_payment_method_ids.each do |distributor_payment_method_id| + expect(page).to have_checked_field( + "order_cycle_selected_distributor_payment_method_ids_#{distributor_payment_method_id}" + ) + end + end + def expect_shipping_methods_to_be_checked_for(distributor) distributor.distributor_shipping_method_ids.each do |distributor_shipping_method_id| expect(page).to have_checked_field(