From c09dc0302d06958f168286da27af3c105b30d3a1 Mon Sep 17 00:00:00 2001 From: Ikraam Ghoor Date: Mon, 1 Feb 2021 08:50:05 +0200 Subject: [PATCH] Migrate default billing addresses to address book `Spree::User` records have a `bill_address_id` that denotes their saved billing address to be reused in the next checkout. That column, however, is not in use since Solidus 2.11.0. Instead, we rely on a`default_billing` Boolean on the `spree_user_addresses` join table. This migration sets the `default_billing` flag on that join table for addresses matching the user's default billing address and the user's ID. For stores that have already started using the `default_billing` Boolean, this task excludes the user_addresses that are already using the new format by setting those `bill_address_id`s to `nil` before running the query. Co-authored-by: mamhoff Co-authored-by: DanielePalombo --- CHANGELOG.md | 8 ++ ...fault_billing_addresses_to_address_book.rb | 33 -------- ...ult_billing_addresses_to_address_book.rake | 38 +++++++++ core/lib/tasks/upgrade.rake | 10 +++ ..._billing_addresses_to_address_book_spec.rb | 77 +++++++++++++++++++ 5 files changed, 133 insertions(+), 33 deletions(-) delete mode 100644 core/db/migrate/20201111133031_migrate_default_billing_addresses_to_address_book.rb create mode 100644 core/lib/tasks/migrations/migrate_default_billing_addresses_to_address_book.rake create mode 100644 core/lib/tasks/upgrade.rake create mode 100644 core/spec/lib/tasks/migrations/migrate_default_billing_addresses_to_address_book_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index df6cdcb314..ecaca726a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## Solidus 3.0.0 (master, unreleased) +Migrated default billing addresses to address book + +Spree::User records have a default bill_address_id that is not in use since +Solidus 2.11.0. Instead, we rely on a default_billing Boolean on the +spree_user_addresses join table. +Please run `rake solidus:upgrade:two_point_eleven` +to make sure your default addresses are migrated accordingly. + ## Solidus 2.11.0 (2020-10-23) ### Major Changes diff --git a/core/db/migrate/20201111133031_migrate_default_billing_addresses_to_address_book.rb b/core/db/migrate/20201111133031_migrate_default_billing_addresses_to_address_book.rb deleted file mode 100644 index ac4eb2f22f..0000000000 --- a/core/db/migrate/20201111133031_migrate_default_billing_addresses_to_address_book.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -class MigrateDefaultBillingAddressesToAddressBook < ActiveRecord::Migration[5.2] - def up - if Spree::UserAddress.where(default_billing: true).any? - Rails.logger.info("This migration seems to have run before in this environment.") - return true - end - - adapter_type = connection.adapter_name.downcase.to_sym - if adapter_type == :mysql2 - sql = <<~SQL - UPDATE spree_user_addresses - JOIN spree_users ON spree_user_addresses.user_id = spree_users.id - AND spree_user_addresses.address_id = spree_users.bill_address_id - SET spree_user_addresses.default_billing = true - SQL - else - sql = <<~SQL - UPDATE spree_user_addresses - SET default_billing = true - FROM spree_users - WHERE spree_user_addresses.address_id = spree_users.bill_address_id - AND spree_user_addresses.user_id = spree_users.id; - SQL - end - execute sql - end - - def down - Spree::UserAddress.update_all(default_billing: false) # rubocop:disable Rails/SkipsModelValidations - end -end diff --git a/core/lib/tasks/migrations/migrate_default_billing_addresses_to_address_book.rake b/core/lib/tasks/migrations/migrate_default_billing_addresses_to_address_book.rake new file mode 100644 index 0000000000..d441834bc4 --- /dev/null +++ b/core/lib/tasks/migrations/migrate_default_billing_addresses_to_address_book.rake @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +namespace :solidus do + namespace :migrations do + namespace :migrate_default_billing_addresses_to_address_book do + task up: :environment do + print "Migrating default billing addresses to address book ... " + if Spree::UserAddress.where(default_billing: true).any? + Spree::LegacyUser.joins(:bill_address).update_all(bill_address_id: nil) # rubocop:disable Rails/SkipsModelValidations + end + adapter_type = Spree::Base.connection.adapter_name.downcase.to_sym + if adapter_type == :mysql2 + sql = <<~SQL + UPDATE spree_user_addresses + JOIN spree_users ON spree_user_addresses.user_id = spree_users.id + AND spree_user_addresses.address_id = spree_users.bill_address_id + SET spree_user_addresses.default_billing = true + SQL + else + sql = <<~SQL + UPDATE spree_user_addresses + SET default_billing = true + FROM spree_users + WHERE spree_user_addresses.address_id = spree_users.bill_address_id + AND spree_user_addresses.user_id = spree_users.id; + SQL + end + Spree::Base.connection.execute sql + puts "Success" + end + + task down: :environment do + Spree::UserAddress.update_all(default_billing: false) # rubocop:disable Rails/SkipsModelValidations + puts "Rolled back default billing address migration to address book" + end + end + end +end diff --git a/core/lib/tasks/upgrade.rake b/core/lib/tasks/upgrade.rake new file mode 100644 index 0000000000..2f81c2596b --- /dev/null +++ b/core/lib/tasks/upgrade.rake @@ -0,0 +1,10 @@ +namespace :solidus do + namespace :upgrade do + desc "Upgrade Solidus to version 2.11.0" + task two_point_eleven: [ + 'solidus:migrations:migrate_default_billing_addresses_to_address_book:up' + ] do + puts "Your Solidus install is ready for Solidus 2.11.0" + end + end +end diff --git a/core/spec/lib/tasks/migrations/migrate_default_billing_addresses_to_address_book_spec.rb b/core/spec/lib/tasks/migrations/migrate_default_billing_addresses_to_address_book_spec.rb new file mode 100644 index 0000000000..52b0a6d3f9 --- /dev/null +++ b/core/spec/lib/tasks/migrations/migrate_default_billing_addresses_to_address_book_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'solidus:migrations:migrate_default_billing_addresses_to_address_book' do + describe 'up' do + include_context( + 'rake', + task_path: Spree::Core::Engine.root.join('lib/tasks/migrations/migrate_default_billing_addresses_to_address_book.rake'), + task_name: 'solidus:migrations:migrate_default_billing_addresses_to_address_book:up', + ) + + let(:user1) { create(:user) } + let(:user2) { create(:user) } + let(:bill_address1) { FactoryBot.create(:address) } + let(:bill_address2) { FactoryBot.create(:address) } + let(:bill_address3) { FactoryBot.create(:address) } + + before do + # Set two billing addresses for User1, the second address is the default. + user1.save_in_address_book(bill_address1.attributes, false, :billing) + user1.save_in_address_book(bill_address2.attributes, true, :billing) + + # Update the "bill_address_id" for user1 to be diffirent from the address_book's default address. + user1.update!(bill_address_id: bill_address1.id) + + # Set user2's bill address using old `bill_address_id` method. + user2.save_in_address_book(bill_address3.attributes, false, :billing) + user2.update!(bill_address_id: bill_address3.id) + Spree::UserAddress.where(user_id: user2.id).first.update!(default_billing: false) + end + + it 'runs' do + expect { task.invoke }.to output( + "Migrating default billing addresses to address book ... Success\n" + ).to_stdout + end + + it "does not migrate a user's `bill_address_id` when a user already has a default `bill_address` in the address book" do + task.invoke + expect(user1.bill_address_id).not_to eq bill_address2.id + expect(user1.bill_address).to eq bill_address2 + end + + it "migrates a user's `bill_address_id` when a user does not have a default `bill_address` in the address book" do + task.invoke + expect(user2.bill_address_id).to eq bill_address3.id + expect(user2.bill_address).to eq bill_address3 + end + end + + describe 'down' do + include_context( + 'rake', + task_path: Spree::Core::Engine.root.join('lib/tasks/migrations/migrate_default_billing_addresses_to_address_book.rake'), + task_name: 'solidus:migrations:migrate_default_billing_addresses_to_address_book:down', + ) + + let(:user) { create(:user) } + let(:bill_address) { FactoryBot.create(:address) } + + before do + user.save_in_address_book(bill_address.attributes, true, :billing) + end + + it 'runs' do + expect { task.invoke }.to output( + "Rolled back default billing address migration to address book\n" + ).to_stdout + end + + it "Rolls back default billing address migration to address book" do + task.invoke + expect(user.bill_address).to eq nil + end + end +end