A shop won't be shown as open if it doesn't have useable shipping method so these shipping method validations are really necessary

This commit is contained in:
Cillian O'Ruanaidh
2022-06-24 16:39:37 +01:00
committed by Filipe
parent a3a52a07b7
commit 593da4996f
8 changed files with 15 additions and 258 deletions

View File

@@ -179,7 +179,8 @@ class OrderCycle < ApplicationRecord
oc.schedule_ids = schedule_ids
oc.save!
exchanges.each { |e| e.clone!(oc) }
oc.selected_shipping_method_ids = selected_shipping_method_ids
oc.selected_shipping_method_ids = attachable_shipping_methods.map(&:id) &
selected_shipping_method_ids
sync_subscriptions
oc.reload
end

View File

@@ -5,42 +5,10 @@ class OrderCycleShippingMethod < ApplicationRecord
belongs_to :shipping_method, class_name: "Spree::ShippingMethod"
validate :shipping_method_belongs_to_order_cycle_distributor
validate :shipping_method_available_at_checkout
validate :order_cycle_not_simple
validates :shipping_method, uniqueness: { scope: :order_cycle_id }
before_destroy :check_shipping_method_not_selected_on_any_orders
private
def shipping_method_not_selected_on_any_orders?
Spree::Order.joins(shipments: :shipping_rates).where(
"order_cycle_id = ? AND spree_shipping_rates.shipping_method_id = ?",
order_cycle_id, shipping_method_id
).empty?
end
def check_shipping_method_not_selected_on_any_orders
return if order_cycle.nil? ||
shipping_method.nil? ||
shipping_method_not_selected_on_any_orders?
errors.add(:base, :shipping_method_already_used_in_order_cycle)
throw :abort
end
def order_cycle_not_simple
return if order_cycle.nil? || !order_cycle.simple?
errors.add(:order_cycle, :must_not_be_simple)
end
def shipping_method_available_at_checkout
return if shipping_method.nil? || shipping_method.frontend?
errors.add(:shipping_method, :must_be_available_at_checkout)
end
def shipping_method_belongs_to_order_cycle_distributor
return if order_cycle.nil? ||
shipping_method.nil? ||

View File

@@ -30,11 +30,8 @@ module Spree
validates :name, presence: true
validate :distributor_validation
validate :at_least_one_shipping_category
validate :switching_to_backoffice_only_wont_leave_order_cycles_without_shipping_methods
validates :display_on, inclusion: { in: DISPLAY_ON_OPTIONS.values }, allow_nil: true
before_destroy :check_destroy_wont_leave_order_cycles_without_shipping_methods
after_save :touch_distributors
scope :managed_by, lambda { |user|
@@ -140,19 +137,5 @@ module Spree
def distributor_validation
validates_with DistributorsValidator
end
def check_destroy_wont_leave_order_cycles_without_shipping_methods
return if no_active_or_upcoming_order_cycle_distributors_with_only_one_shipping_method?
errors.add(:base, :destroy_leaves_order_cycles_without_shipping_methods)
throw :abort
end
def switching_to_backoffice_only_wont_leave_order_cycles_without_shipping_methods
return if frontend? ||
no_active_or_upcoming_order_cycle_distributors_with_only_one_shipping_method?
errors.add(:base, :switching_to_backoffice_only_leaves_order_cycles_without_shipping_methods)
end
end
end

View File

@@ -73,25 +73,13 @@ en:
attributes:
base:
card_expired: "has expired"
spree/shipping_method:
attributes:
base:
switching_to_backoffice_only_leaves_order_cycles_without_shipping_methods: Unable to switch to backoffice only, some open or upcoming order cycles would be left without any shipping methods
destroy_leaves_order_cycles_without_shipping_methods: Unable to delete, some open or upcoming order cycles would be left without any shipping methods
order_cycle:
attributes:
base:
at_least_one_shipping_method_per_distributor: "You need to select at least one shipping method for each distributor"
orders_close_at:
after_orders_open_at: must be after open date
order_cycle_shipping_method:
attributes:
base:
shipping_method_already_used_in_order_cycle: "This shipping method has already been selected on orders in this order cycle and cannot be removed"
order_cycle:
must_not_be_simple: "is simple, all shipping methods are available by default and cannot be customised"
shipping_method:
must_be_available_at_checkout: "must be available at checkout"
must_belong_to_order_cycle_distributor: "must be from a distributor on the order cycle"
variant_override:
count_on_hand:

View File

@@ -3,55 +3,6 @@
require 'spec_helper'
describe OrderCycleShippingMethod do
it "is valid when the shipping method is available at checkout" do
shipping_method = create(:shipping_method, display_on: nil)
enterprise = create(:enterprise, shipping_methods: [shipping_method])
order_cycle = create(:simple_order_cycle, distributors: [enterprise])
order_cycle_shipping_method = OrderCycleShippingMethod.new(
order_cycle: order_cycle,
shipping_method: shipping_method
)
expect(order_cycle_shipping_method).to be_valid
shipping_method.display_on = "both"
expect(order_cycle_shipping_method).to be_valid
end
it "is not valid when the shipping method is only available in the backoffice" do
shipping_method = create(:shipping_method, display_on: "back_end")
enterprise = create(:enterprise, shipping_methods: [shipping_method])
order_cycle = create(:simple_order_cycle, distributors: [enterprise])
order_cycle_shipping_method = OrderCycleShippingMethod.new(
order_cycle: order_cycle,
shipping_method: shipping_method
)
expect(order_cycle_shipping_method).to_not be_valid
expect(order_cycle_shipping_method.errors.to_a).to include(
"Shipping method must be available at checkout"
)
end
it "is not valid if the order cycle is simple i.e. :sells is 'own'" do
order_cycle = create(:sells_own_order_cycle)
shipping_method = create(:shipping_method, distributors: [order_cycle.coordinator])
order_cycle_shipping_method = OrderCycleShippingMethod.new(
order_cycle: order_cycle,
shipping_method: shipping_method
)
expect(order_cycle_shipping_method).to_not be_valid
expect(order_cycle_shipping_method.errors.to_a).to include(
"Order cycle is simple, all shipping methods are available by default and cannot be " \
"customised"
)
end
it "is valid if the shipping method belongs to one of the order cycle distributors" do
shipping_method = create(:shipping_method)
enterprise = create(:enterprise, shipping_methods: [shipping_method])
@@ -80,37 +31,4 @@ describe OrderCycleShippingMethod do
"Shipping method must be from a distributor on the order cycle"
]
end
it "can be destroyed if the shipping method hasn't been used on any orders in the order cycle" do
shipping_method = create(:shipping_method)
enterprise = create(:enterprise, shipping_methods: [shipping_method])
order_cycle = create(:simple_order_cycle, distributors: [enterprise])
order_cycle_shipping_method = OrderCycleShippingMethod.create!(
order_cycle: order_cycle,
shipping_method: shipping_method
)
order_cycle_shipping_method.destroy
expect(order_cycle_shipping_method).to be_destroyed
end
it "cannot be destroyed if the shipping method has been used on some orders in the order cycle" do
shipping_method = create(:shipping_method)
enterprise = create(:enterprise, shipping_methods: [shipping_method])
order_cycle = create(:simple_order_cycle, distributors: [enterprise])
order = create(:order_ready_for_payment, distributor: enterprise, order_cycle: order_cycle)
order_cycle_shipping_method = OrderCycleShippingMethod.create!(
order_cycle: order_cycle,
shipping_method: shipping_method
)
order_cycle_shipping_method.destroy
expect(order_cycle_shipping_method).not_to be_destroyed
expect(order_cycle_shipping_method.errors.to_a).to eq [
"This shipping method has already been selected on orders in this order cycle and cannot " \
"be removed"
]
end
end

View File

@@ -406,17 +406,20 @@ describe OrderCycle do
context "when it has preferred shipping methods which can longer be applied validly
e.g. shipping method is backoffice only" do
it "raises an error (TODO: display a message to user explaining why clone failed)" do
it "only attaches the valid ones to the clone" do
distributor = create(:distributor_enterprise)
shipping_method = create(:shipping_method, distributors: [distributor])
shipping_method_i = create(:shipping_method, distributors: [distributor])
shipping_method_ii = create(
:shipping_method,
distributors: [distributor],
display_on: Spree::ShippingMethod::DISPLAY_ON_OPTIONS[:back_end]
)
order_cycle = create(:distributor_order_cycle, distributors: [distributor])
order_cycle.selected_shipping_methods << shipping_method
order_cycle.selected_shipping_methods = [shipping_method_i, shipping_method_ii]
shipping_method.update_column(:display_on, "back_end")
cloned_order_cycle = order_cycle.clone!
expect {
order_cycle.clone!
}.to raise_error ActiveRecord::RecordInvalid
expect(cloned_order_cycle.shipping_methods).to eq [shipping_method_i]
end
end
end

View File

@@ -182,47 +182,6 @@ module Spree
it { expect(shipping_method).to be_valid }
end
end
context "when it is being changed to backoffice only" do
let!(:order_cycle) { create(:distributor_order_cycle, distributors: [distributor]) }
let(:distributor) { create(:distributor_enterprise, shipping_methods: [shipping_method]) }
let(:shipping_method) { create(:shipping_method) }
context "when one of its distributors has no other shipping methods available
on an active or upcoming order cycle" do
it "should not be valid" do
shipping_method.display_on = "back_end"
expect(shipping_method).not_to be_valid
expect(shipping_method.errors.to_a).to eq [
"Unable to switch to backoffice only, some open or upcoming order cycles would be " \
"left without any shipping methods"
]
end
end
context "when one of its distributors has no other shipping methods available
on an order cycle which isn't active or upcoming" do
it "is valid" do
order_cycle.update!(orders_open_at: 2.weeks.ago, orders_close_at: 1.week.ago)
shipping_method.display_on = "back_end"
expect(shipping_method).to be_valid
end
end
context "when one of its distributors has other shipping methods available
on an active or upcoming order cycle" do
it "is valid" do
create(:shipping_method, distributors: [distributor])
shipping_method.display_on = "back_end"
expect(shipping_method).to be_valid
end
end
end
end
# Regression test for Spree #4320
@@ -256,68 +215,5 @@ module Spree
expect(shipping_method.shipments).to include(shipment)
end
end
context "#destroy" do
let(:shipping_method) { create(:shipping_method) }
let(:distributor) { create(:distributor_enterprise, shipping_methods: [shipping_method]) }
let!(:order_cycle) { create(:distributor_order_cycle, distributors: [distributor]) }
context "when its distributors are part of some order cycles
and have no other shipping methods available" do
it "can be deleted if the order cycle is closed" do
order_cycle.update!(orders_close_at: 1.minute.ago)
shipping_method.destroy
expect(shipping_method).to be_deleted
end
it "cannot be deleted if the order cycle is active" do
order_cycle.update!(orders_open_at: 1.day.ago, orders_close_at: 1.week.from_now)
shipping_method.destroy
expect(shipping_method).not_to be_deleted
expect(shipping_method.errors.to_a).to eq [
"Unable to delete, some open or upcoming order cycles would be left without any " \
"shipping methods"
]
end
it "cannot be deleted if the order cycle is upcoming" do
order_cycle.update!(orders_open_at: 1.day.from_now, orders_close_at: 1.week.from_now)
shipping_method.destroy
expect(shipping_method).not_to be_deleted
expect(shipping_method.errors.to_a).to eq [
"Unable to delete, some open or upcoming order cycles would be left without any " \
"shipping methods"
]
end
end
context "when its distributors are part of some active or upcoming order cycles
and have other shipping methods available" do
it "can be deleted" do
create(:shipping_method, distributors: [distributor])
shipping_method.destroy
expect(shipping_method).to be_deleted
end
end
context "when its distributors have no other shipping methods available
but aren't part of active/upcoming order cycles" do
it "can be deleted" do
order_cycle.update!(orders_open_at: 2.weeks.ago, orders_close_at: 1.week.ago)
shipping_method.destroy
expect(shipping_method).to be_deleted
end
end
end
end
end

View File

@@ -247,15 +247,15 @@ describe OrderCycleForm do
shipping_method_i = create(:shipping_method, distributors: [distributor_i])
shipping_method_ii = create(:shipping_method, distributors: [distributor_ii])
order_cycle = create(:distributor_order_cycle,
distributors: [distributor_i, distributor_ii])
distributors: [distributor_i])
form = OrderCycleForm.new(order_cycle,
{ selected_shipping_method_ids: [shipping_method_i.id] },
{ selected_shipping_method_ids: [shipping_method_ii.id] },
order_cycle.coordinator)
expect(form.save).to be false
expect(order_cycle.errors.to_a).to eq [
"You need to select at least one shipping method for each distributor"
"Shipping method must be from a distributor on the order cycle"
]
end
end