diff --git a/app/helpers/enterprises_helper.rb b/app/helpers/enterprises_helper.rb index 394f4ae1a07..6251923c10d 100644 --- a/app/helpers/enterprises_helper.rb +++ b/app/helpers/enterprises_helper.rb @@ -12,7 +12,12 @@ def current_customer end def available_shipping_methods - DistributorShippingMethods.shipping_methods(current_distributor, true, current_customer) + DistributorShippingMethods.shipping_methods( + distributor: current_distributor, + checkout: true, + customer: current_customer, + apply_tags: true + ) end def available_payment_methods diff --git a/app/models/spree/shipment.rb b/app/models/spree/shipment.rb index e706c3dbac5..1954902928e 100644 --- a/app/models/spree/shipment.rb +++ b/app/models/spree/shipment.rb @@ -103,12 +103,13 @@ def selected_shipping_rate_id=(id) save! end - def refresh_rates + def refresh_rates(apply_tags = true) return shipping_rates if shipped? # The call to Stock::Estimator below will replace the current shipping_method original_shipping_method_id = shipping_method.try(:id) - self.shipping_rates = OrderManagement::Stock::Estimator.new(order).shipping_rates(to_package) + self.shipping_rates = + OrderManagement::Stock::Estimator.new(order).shipping_rates(to_package, true, apply_tags) keep_original_shipping_method_selection(original_shipping_method_id) diff --git a/app/services/distributor_shipping_methods.rb b/app/services/distributor_shipping_methods.rb index 04e4b450359..cb589ba97e7 100644 --- a/app/services/distributor_shipping_methods.rb +++ b/app/services/distributor_shipping_methods.rb @@ -1,16 +1,18 @@ # frozen_string_literal: true class DistributorShippingMethods - def self.shipping_methods(distributor, checkout = false, customer = nil) + def self.shipping_methods(distributor:, checkout: false, apply_tags: true, customer: nil) return [] if distributor.blank? shipping_methods = distributor.shipping_methods shipping_methods = shipping_methods.display_on_checkout if checkout shipping_methods = shipping_methods.to_a - OpenFoodNetwork::TagRuleApplicator.new( - distributor, "FilterShippingMethods", customer&.tag_list - ).filter!(shipping_methods) + if apply_tags + OpenFoodNetwork::TagRuleApplicator.new( + distributor, "FilterShippingMethods", customer&.tag_list + ).filter!(shipping_methods) + end shipping_methods.uniq end diff --git a/engines/order_management/app/services/order_management/stock/estimator.rb b/engines/order_management/app/services/order_management/stock/estimator.rb index c97d9c3b99c..03a1fb46972 100644 --- a/engines/order_management/app/services/order_management/stock/estimator.rb +++ b/engines/order_management/app/services/order_management/stock/estimator.rb @@ -10,9 +10,9 @@ def initialize(order) @currency = order.currency end - def shipping_rates(package, frontend_only = true) + def shipping_rates(package, frontend_only = true, apply_tags = true) shipping_rates = [] - shipping_methods = shipping_methods(package) + shipping_methods = shipping_methods(package, apply_tags) return [] unless shipping_methods shipping_methods.each do |shipping_method| @@ -40,8 +40,12 @@ def shipping_rates(package, frontend_only = true) private - def shipping_methods(package) - shipping_methods = package.shipping_methods + def shipping_methods(package, apply_tags) + shipping_methods = if apply_tags + package.filtered_shipping_methods + else + package.shipping_methods + end shipping_methods.delete_if { |ship_method| !ship_method.calculator.available?(package) } shipping_methods.delete_if { |ship_method| !ship_method.include?(order.ship_address) } shipping_methods.delete_if { |ship_method| diff --git a/engines/order_management/app/services/order_management/stock/package.rb b/engines/order_management/app/services/order_management/stock/package.rb index 8f5002a7f49..518c2953505 100644 --- a/engines/order_management/app/services/order_management/stock/package.rb +++ b/engines/order_management/app/services/order_management/stock/package.rb @@ -79,11 +79,22 @@ def currency # TODO calculate from first variant? end - # Skips the methods that are not used by the order's distributor - # - # @return [Array] def shipping_methods - DistributorShippingMethods.shipping_methods(order.distributor, false, order.customer) + DistributorShippingMethods.shipping_methods( + distributor: order.distributor, + checkout: false, + customer: order.customer, + apply_tags: false + ) + end + + def filtered_shipping_methods + DistributorShippingMethods.shipping_methods( + distributor: order.distributor, + checkout: false, + customer: order.customer, + apply_tags: true + ) end def inspect diff --git a/spec/services/distributor_shipping_methods_spec.rb b/spec/services/distributor_shipping_methods_spec.rb new file mode 100644 index 00000000000..489c55d5e3b --- /dev/null +++ b/spec/services/distributor_shipping_methods_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe DistributorShippingMethods do + let!(:enterprise) { create(:distributor_enterprise) } + let!(:shipping_method) { create(:shipping_method, distributors: [enterprise]) } + let!(:member_shipping_method) { create(:shipping_method, distributors: [enterprise]) } + let!(:backend_shipping_method) { create(:shipping_method, distributors: [enterprise]) } + let!(:customer) { create(:customer) } + let!(:sm_tag_rule) { + create( + :filter_shipping_methods_tag_rule, + enterprise: enterprise, + priority: 2, + preferred_customer_tags: "member", + preferred_shipping_method_tags: "member", + preferred_matched_shipping_methods_visibility: "visible" + ) + } + + let!(:default_sm_tag_rule) { + create( + :filter_shipping_methods_tag_rule, + enterprise: enterprise, + priority: 1, + is_default: true, + preferred_shipping_method_tags: [], + preferred_customer_tags: [], + preferred_matched_shipping_methods_visibility: "hidden" + ) + } + + it "returns all shipping methods for a distributor" do + expect(DistributorShippingMethods.shipping_methods(distributor: enterprise).count).to eq(3) + end + + it "does not return a shipping method tagged as 'member' for a customer without that tag" do + member_shipping_method.tag_list << "member" + member_shipping_method.save + result = + DistributorShippingMethods.shipping_methods(distributor: enterprise, customer: customer) + expect(result).to include(shipping_method) + expect(result).to include(backend_shipping_method) + end + + it "returns the shipping method tagged 'member' for a customer with that tag" do + member_customer = create(:customer) + member_customer.tag_list << "member" + member_customer.save + member_shipping_method.tag_list << "member" + member_shipping_method.save + result = DistributorShippingMethods.shipping_methods( + distributor: enterprise, customer: member_customer + ) + expect(result).to include(member_shipping_method) + end + + it "does not return a non-checkout shipping method if passed checkout=true" do + backend_shipping_method.display_on = "back_end" + backend_shipping_method.save + result = DistributorShippingMethods.shipping_methods( + distributor: enterprise, checkout: true, customer: customer + ) + expect(result).to include(shipping_method) + end +end