diff --git a/core/db/default/spree/states.rb b/core/db/default/spree/states.rb index 36645071f27..72a75c43780 100644 --- a/core/db/default/spree/states.rb +++ b/core/db/default/spree/states.rb @@ -1,14 +1,24 @@ # frozen_string_literal: true +countries_that_use_nested_subregions = %w(IT) + +def create_states(subregions, country) + subregions.each do |subregion| + Spree::State.where(abbr: subregion.code, country: country).first_or_create!( + name: subregion.name + ) + end +end + ActiveRecord::Base.transaction do Spree::Country.all.each do |country| carmen_country = Carmen::Country.coded(country.iso) next unless carmen_country.subregions? - carmen_country.subregions.each do |subregion| - Spree::State.where(abbr: subregion.code, country: country).first_or_create!( - name: subregion.name - ) + if countries_that_use_nested_subregions.include? country.iso + create_states(carmen_country.subregions.flat_map(&:subregions), country) + else + create_states(carmen_country.subregions, country) end end end diff --git a/core/lib/tasks/states.rake b/core/lib/tasks/states.rake new file mode 100644 index 00000000000..d88eeace2fd --- /dev/null +++ b/core/lib/tasks/states.rake @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +def get_carmen_states(iso) + carmen_country = Carmen::Country.coded(iso) + return false unless carmen_country&.subregions? + + if %w(IT).include? iso + return carmen_country.subregions.flat_map(&:subregions) + else + return carmen_country.subregions + end +end + +def user_agrees(destroy_states, create_states, country) + puts "\e[31mStates for #{country.name} are incorrect. If you proceed, the following changes will happen:\e[0m" + puts "\e[31mThese states will be destroyed:\e[0m #{destroy_states}" + puts "\e[31mThese states will be created:\e[0m #{create_states}" + puts "\e[31mDo you want to proceed? [y/n]\e[0m " + ["y", "yes"].include? STDIN.gets.strip.downcase +end + +def delete_states(country, carmen_names) + country.states.where.not(name: carmen_names).destroy_all +end + +def create_states(country, carmen_states, state_names) + carmen_states.each do |state| + unless state_names.include? state.name + Spree::State.where(abbr: state.code, country: country).first_or_create!( + name: state.name + ) + end + end +end + +namespace :states do + desc "Regenerates states in cases where previous Solidus versions generated incorrect states" + task regenerate: :environment do + Spree::Country.all.each do |country| + if carmen_states = get_carmen_states(country.iso) + if (state_names = country.states.pluck(:name)) != (carmen_names = carmen_states.map(&:name).sort) + if user_agrees( + (state_names - carmen_names), + (carmen_names - state_names), + country + ) + delete_states(country, carmen_names) + create_states(country, carmen_states, state_names) + puts "#{country} states have been regenerated" + else + puts "Skipping #{country}" + end + end + end + end + end +end