diff --git a/backend/app/assets/javascripts/spree/backend/views/state_select.js b/backend/app/assets/javascripts/spree/backend/views/state_select.js index e43759b1c2e..d5bd3bb26ea 100644 --- a/backend/app/assets/javascripts/spree/backend/views/state_select.js +++ b/backend/app/assets/javascripts/spree/backend/views/state_select.js @@ -39,11 +39,11 @@ Spree.Views.StateSelect = Backbone.View.extend({ }, render: function() { - this.$state_select.empty().hide(); - this.$state_input.hide(); + this.$state_select.empty().hide().prop('disabled', true); + this.$state_input.hide().prop('disabled', true); if (!this.states.fetched) { - this.$state_select.show().prop("disabled", true); + this.$state_select.show(); } else if (this.states.length) { var $state_select = this.$state_select; this.states.each(function(state) { @@ -54,7 +54,7 @@ Spree.Views.StateSelect = Backbone.View.extend({ this.$state_select.val(this.model.get("state_id")) this.$state_select.show().prop("disabled", false); } else { - this.$state_input.prop('disabled', false).show(); + this.$state_input.show().prop('disabled', false); } } }) diff --git a/backend/app/views/spree/admin/shared/_address_form.html.erb b/backend/app/views/spree/admin/shared/_address_form.html.erb index 443b8e6662e..4dc5e060a35 100644 --- a/backend/app/views/spree/admin/shared/_address_form.html.erb +++ b/backend/app/views/spree/admin/shared/_address_form.html.erb @@ -48,9 +48,11 @@
"> <%= f.label :state_id, Spree::State.model_name.human %> + <%= f.hidden_field :state_name, value: nil %> <%= f.text_field :state_name, style: "display: #{f.object.country.states.empty? ? 'block' : 'none' };", disabled: !f.object.country.states.empty?, class: 'fullwidth state_name js-state_name' %> + <%= f.hidden_field :state_id, value: nil %> <%= f.collection_select :state_id, f.object.country.states.sort, :id, :name, {include_blank: true}, {class: 'custom-select fullwidth js-state_id', style: "display: #{f.object.country.states.empty? ? 'none' : 'block' };", disabled: f.object.country.states.empty?} %>
diff --git a/core/app/models/spree/address.rb b/core/app/models/spree/address.rb index 101eb916c8f..710037c2f44 100644 --- a/core/app/models/spree/address.rb +++ b/core/app/models/spree/address.rb @@ -14,6 +14,7 @@ class Address < Spree::Base validates :phone, presence: true, if: :require_phone? validate :state_validate + validate :validate_state_matches_country alias_attribute :first_name, :firstname alias_attribute :last_name, :lastname @@ -209,5 +210,11 @@ def state_validate # ensure at least one state field is populated errors.add :state, :blank if state.blank? && state_name.blank? end + + def validate_state_matches_country + if state && state.country != country + errors.add(:state, :does_not_match_country) + end + end end end diff --git a/core/config/locales/en.yml b/core/config/locales/en.yml index c9a0c121652..9bbfc0cd6df 100644 --- a/core/config/locales/en.yml +++ b/core/config/locales/en.yml @@ -639,6 +639,10 @@ en: other: Zones errors: models: + spree/address: + attributes: + state: + does_not_match_country: does not match the country spree/calculator/tiered_flat_rate: attributes: base: diff --git a/core/spec/models/spree/address_spec.rb b/core/spec/models/spree/address_spec.rb index a38e6711f9c..5f4b05a91d7 100644 --- a/core/spec/models/spree/address_spec.rb +++ b/core/spec/models/spree/address_spec.rb @@ -68,11 +68,24 @@ expect(address.state_name).to be_nil end - it "state is entered but country does not contain that state" do - address.state = state - address.country = Spree::Country.new(states_required: true) - address.valid? - expect(address.errors["state"]).to eq(['is invalid']) + context 'when the country does not match the state' do + context 'when the country requires states' do + it 'is invalid' do + address.state = state + address.country = Spree::Country.new(states_required: true) + address.valid? + expect(address.errors["state"]).to eq(['is invalid', 'does not match the country']) + end + end + + context 'when the country does not require states' do + it 'is invalid' do + address.state = state + address.country = Spree::Country.new(states_required: false) + address.valid? + expect(address.errors["state"]).to eq(['does not match the country']) + end + end end it "both state and state_name are entered but country does not contain the state" do