From ccbf20a73bba5792cf78c98cfa646fb4ab6d88fe Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 13 Sep 2022 15:47:53 +1000 Subject: [PATCH 01/15] Replace spec of customer's internal logic Specs should test public methods. Private methods should be able to change without specs breaking. The specs were also just mirroring the code and didn't really have any meaning. So I wrote new ones which are hopefully clearer. There's actually a case which I don't quite understand. Why don't we require a customer for a new complete order? It means that we don't have a customer creating it but then it's added when updating the order. Seems inconsistent. --- spec/models/spree/order_spec.rb | 48 +++++++++++---------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index c490457aa3..808174c04a 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -893,45 +893,27 @@ describe Spree::Order do end end - describe "#require_customer?" do - context "when the record is new" do - let(:order) { build(:order, state: state) } - - context "and the state is not cart" do - let(:state) { "complete" } - - it "returns false" do - expect(order.send(:require_customer?)).to eq(false) - end - end - - context "and the state is cart" do - let(:state) { "cart" } - - it "returns false" do - expect(order.send(:require_customer?)).to eq(false) - end - end + describe "#customer" do + it "is not required for new records" do + is_expected.to_not validate_presence_of(:customer) end - context "when the record is not new" do - let(:order) { create(:order, state: state) } + it "is not required for new complete orders" do + order = Spree::Order.new(state: "complete") - context "and the state is not cart" do - let(:state) { "complete" } + expect(order).to_not validate_presence_of(:customer) + end - it "returns true" do - expect(order.send(:require_customer?)).to eq(true) - end - end + it "is not required for existing orders in cart state" do + order = create(:order) - context "and the state is cart" do - let(:state) { "cart" } + expect(order).to_not validate_presence_of(:customer) + end - it "returns false" do - expect(order.send(:require_customer?)).to eq(false) - end - end + it "is created for existing orders in complete state" do + order = create(:order, state: "complete") + + expect { order.valid? }.to change { order.customer }.from(nil) end end From 0d1f48ac0d200f702952d0000f5e84c7a779c249 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 13 Sep 2022 16:56:25 +1000 Subject: [PATCH 02/15] Simplify order-customer logic --- app/models/spree/order.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index f161da24e9..4f5c22938b 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -704,9 +704,7 @@ module Spree end def require_customer? - return false if new_record? || state == 'cart' - - true + persisted? && state != "cart" end def customer_is_valid? From 93da64f4663bd4867dde8424e0911dec7e3a0a3e Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 14 Sep 2022 14:42:23 +1000 Subject: [PATCH 03/15] Spec for duplicate customers after changing email --- spec/models/spree/order_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index 808174c04a..113f7fc8bb 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -973,6 +973,21 @@ describe Spree::Order do expect(order.customer).to be_present end + + it "recognises users with changed email address" do + pending "#9002" + + order.update!(state: "complete") + + # Change email instantly without confirmation via Devise: + order.user.update_columns(email: "new@email.org") + + other_order = create(:order, user: order.user, distributor: distributor) + + expect { + other_order.update!(state: "complete") + }.to_not change { Customer.count } + end end end From 5fefd3b14b84774eaf5e6b0e9b4afcf30658dcf3 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 14 Sep 2022 15:17:00 +1000 Subject: [PATCH 04/15] Remove useless customer loading and clarify name The method `associate_customer` only loads a customer but doesn't actually associate one. So the deleted line doesn't have any effect. The intention was to reset the customer after switching shops but the before_validation logic on the order model takes care of that already. I'm renaming this private method here for clarity. --- app/models/spree/order.rb | 4 ++-- app/services/order_cart_reset.rb | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index 4f5c22938b..d23e8f71a7 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -717,7 +717,7 @@ module Spree (user&.email || email)&.downcase end - def associate_customer + def find_customer return customer if customer.present? Customer.of(distributor).find_by(email: email_for_customer) @@ -738,7 +738,7 @@ module Spree end def ensure_customer - self.customer = associate_customer || create_customer + self.customer = find_customer || create_customer end def update_adjustment!(adjustment) diff --git a/app/services/order_cart_reset.rb b/app/services/order_cart_reset.rb index 4faec18a30..216a6fbbc1 100644 --- a/app/services/order_cart_reset.rb +++ b/app/services/order_cart_reset.rb @@ -30,7 +30,6 @@ class OrderCartReset return unless current_user order.associate_user!(current_user) if order.user.blank? || order.email.blank? - order.__send__(:associate_customer) if order.customer.nil? # Only associates existing customers end def reset_order_cycle(current_customer) From cf634d8d9bbe0c03839ad5aa78feef501343d413 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 14 Sep 2022 15:22:11 +1000 Subject: [PATCH 05/15] Simplify customer association --- app/models/spree/order.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index d23e8f71a7..d6c8c1d3b8 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -718,8 +718,6 @@ module Spree end def find_customer - return customer if customer.present? - Customer.of(distributor).find_by(email: email_for_customer) end @@ -738,7 +736,7 @@ module Spree end def ensure_customer - self.customer = find_customer || create_customer + self.customer ||= find_customer || create_customer end def update_adjustment!(adjustment) From 9dbba35019b7f8df2a0759c697ebbf0bf14f2c3e Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 14 Sep 2022 15:44:45 +1000 Subject: [PATCH 06/15] Find customers by user id as well as email Also fixing up a spec which became brittle due to too much mocking. --- app/models/spree/order.rb | 3 ++- spec/models/spree/order/callbacks_spec.rb | 4 ++-- spec/models/spree/order_spec.rb | 2 -- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index d6c8c1d3b8..cd8a57d959 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -718,7 +718,8 @@ module Spree end def find_customer - Customer.of(distributor).find_by(email: email_for_customer) + user&.customers&.of(distributor)&.first || + Customer.of(distributor).find_by(email: email_for_customer) end def create_customer diff --git a/spec/models/spree/order/callbacks_spec.rb b/spec/models/spree/order/callbacks_spec.rb index a3cb0744ec..ed5b4c2c35 100644 --- a/spec/models/spree/order/callbacks_spec.rb +++ b/spec/models/spree/order/callbacks_spec.rb @@ -21,10 +21,10 @@ describe Spree::Order do context "#save" do context "when associated with a registered user" do - let(:user) { double(:user, email: "test@example.com") } + let(:user) { Spree::User.new(email: "test@example.com") } before do - allow(order).to receive_messages user: user + order.user = user end it "should assign the email address of the user" do diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index 113f7fc8bb..85430bfc0a 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -975,8 +975,6 @@ describe Spree::Order do end it "recognises users with changed email address" do - pending "#9002" - order.update!(state: "complete") # Change email instantly without confirmation via Devise: From f6ac02dce579694bf734152503bc9c2e1c008630 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 27 Sep 2022 14:52:05 +1000 Subject: [PATCH 07/15] Update customer's email after user changed it This may fail if there's already a customer record with the same email address for the same enterprise. I will fix that in the next commit. --- app/models/spree/order.rb | 9 +++++++++ spec/models/spree/order_spec.rb | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index cd8a57d959..018b6b5c8b 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -738,6 +738,15 @@ module Spree def ensure_customer self.customer ||= find_customer || create_customer + + synchronise_customer_email + end + + # Update the customer record if the user changed their email address. + def synchronise_customer_email + if user && customer && user.email != customer.email + customer.update(email: user.email) + end end def update_adjustment!(adjustment) diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index 85430bfc0a..e9e1ab8879 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -985,6 +985,10 @@ describe Spree::Order do expect { other_order.update!(state: "complete") }.to_not change { Customer.count } + + expect(other_order.customer.email).to eq "new@email.org" + expect(order.customer).to eq other_order.customer + expect(order.reload.customer.email).to eq "new@email.org" end end end From b232fa3d0cbf706abdbe9a00806ff93f5c1224d1 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 27 Sep 2022 16:05:20 +1000 Subject: [PATCH 08/15] Deal with conflicting customer entries --- app/models/spree/order.rb | 9 +++++++++ spec/models/spree/order_spec.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index 018b6b5c8b..824143a459 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -745,6 +745,15 @@ module Spree # Update the customer record if the user changed their email address. def synchronise_customer_email if user && customer && user.email != customer.email + duplicate = Customer.find_by(email: user.email, enterprise: distributor) + + if duplicate.present? + Spree::Order.where(customer_id: duplicate.id).update_all(customer_id: customer.id) + Subscription.where(customer_id: duplicate.id).update_all(customer_id: customer.id) + + duplicate.destroy + end + customer.update(email: user.email) end end diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index e9e1ab8879..0f51eb7b7f 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -990,6 +990,33 @@ describe Spree::Order do expect(order.customer).to eq other_order.customer expect(order.reload.customer.email).to eq "new@email.org" end + + it "resolves conflicts with duplicate customer entries" do + order.update!(state: "complete") + + # The user may check out as guest first: + guest_order = create(:order, user: nil, email: "new@email.org", distributor: distributor) + guest_order.update!(state: "complete") + + # Afterwards the user changes their email in their profile. + # Change email instantly without confirmation via Devise: + order.user.update_columns(email: "new@email.org") + + other_order = nil + + # The two customer entries are merged and one is deleted: + expect { + other_order = create(:order, user: order.user, distributor: distributor) + }.to change { Customer.count }.by(-1) + + expect(other_order.customer.email).to eq "new@email.org" + expect(order.customer).to eq other_order.customer + expect(order.reload.customer.email).to eq "new@email.org" + + expect(order.customer.orders).to match_array [ + order, guest_order, other_order + ] + end end end From 37eac5ed492392a9c576a582b9c2fa5117a97007 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 27 Sep 2022 16:59:59 +1000 Subject: [PATCH 09/15] Remove dead code branch in customer check We only try to create a customer when none is present. So the check for validating the customer always returned false because we didn't have a customer. --- app/models/spree/order.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index 824143a459..40de102f03 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -707,12 +707,6 @@ module Spree persisted? && state != "cart" end - def customer_is_valid? - return true unless require_customer? - - customer.present? && customer.enterprise_id == distributor_id && customer.email == email_for_customer - end - def email_for_customer (user&.email || email)&.downcase end @@ -723,7 +717,7 @@ module Spree end def create_customer - return if customer_is_valid? + return unless require_customer? Customer.create( enterprise: distributor, From cec81a3ae60636a3a95cae670d45f208211b6e29 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 27 Sep 2022 17:43:27 +1000 Subject: [PATCH 10/15] Clarify condition to create customer record --- app/models/spree/order.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index 40de102f03..ced4343455 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -717,8 +717,6 @@ module Spree end def create_customer - return unless require_customer? - Customer.create( enterprise: distributor, email: email_for_customer, @@ -731,7 +729,8 @@ module Spree end def ensure_customer - self.customer ||= find_customer || create_customer + self.customer ||= find_customer + self.customer ||= create_customer if require_customer? synchronise_customer_email end From a0260c4ff78cddc1e9da7e17d137930d65143bdf Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 27 Sep 2022 17:53:04 +1000 Subject: [PATCH 11/15] Move customer update logic to own service file The Order class is too big already. We can move more code in the next commits. --- app/models/spree/order.rb | 18 +----------------- app/services/customer_syncer.rb | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 app/services/customer_syncer.rb diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index ced4343455..3ea497287f 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -732,23 +732,7 @@ module Spree self.customer ||= find_customer self.customer ||= create_customer if require_customer? - synchronise_customer_email - end - - # Update the customer record if the user changed their email address. - def synchronise_customer_email - if user && customer && user.email != customer.email - duplicate = Customer.find_by(email: user.email, enterprise: distributor) - - if duplicate.present? - Spree::Order.where(customer_id: duplicate.id).update_all(customer_id: customer.id) - Subscription.where(customer_id: duplicate.id).update_all(customer_id: customer.id) - - duplicate.destroy - end - - customer.update(email: user.email) - end + CustomerSyncer.new(self).synchronise_customer_email end def update_adjustment!(adjustment) diff --git a/app/services/customer_syncer.rb b/app/services/customer_syncer.rb new file mode 100644 index 0000000000..44661bceef --- /dev/null +++ b/app/services/customer_syncer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# Create, find and update customer records. +# +# P.S.: I almost couldn't resist to call this CustomerService. +class CustomerSyncer + attr_reader :customer, :distributor, :user + + def initialize(order) + @customer = order.customer + @distributor = order.distributor + @user = order.user + end + + # Update the customer record if the user changed their email address. + def synchronise_customer_email + if user && customer && user.email != customer.email + duplicate = Customer.find_by(email: user.email, enterprise: distributor) + + if duplicate.present? + Spree::Order.where(customer_id: duplicate.id).update_all(customer_id: customer.id) + Subscription.where(customer_id: duplicate.id).update_all(customer_id: customer.id) + + duplicate.destroy + end + + customer.update(email: user.email) + end + end +end From 33d6454dd34585a0b4c27fe48107de1a74978467 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 27 Sep 2022 18:00:52 +1000 Subject: [PATCH 12/15] Simplify with guard clause --- app/services/customer_syncer.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/services/customer_syncer.rb b/app/services/customer_syncer.rb index 44661bceef..9e0f24b321 100644 --- a/app/services/customer_syncer.rb +++ b/app/services/customer_syncer.rb @@ -14,17 +14,17 @@ class CustomerSyncer # Update the customer record if the user changed their email address. def synchronise_customer_email - if user && customer && user.email != customer.email - duplicate = Customer.find_by(email: user.email, enterprise: distributor) + return unless user && customer && user.email != customer.email - if duplicate.present? - Spree::Order.where(customer_id: duplicate.id).update_all(customer_id: customer.id) - Subscription.where(customer_id: duplicate.id).update_all(customer_id: customer.id) + duplicate = Customer.find_by(email: user.email, enterprise: distributor) - duplicate.destroy - end + if duplicate.present? + Spree::Order.where(customer_id: duplicate.id).update_all(customer_id: customer.id) + Subscription.where(customer_id: duplicate.id).update_all(customer_id: customer.id) - customer.update(email: user.email) + duplicate.destroy end + + customer.update(email: user.email) end end From 1f19642dad7935af5fd34f3bce29192063977e74 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 27 Sep 2022 18:03:09 +1000 Subject: [PATCH 13/15] Simplify Order by outsourcing to service class This is work in progress and calling the service will be simplified in a few commits. --- app/models/spree/order.rb | 14 +------------- app/services/customer_syncer.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index 3ea497287f..aaabdcb497 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -716,21 +716,9 @@ module Spree Customer.of(distributor).find_by(email: email_for_customer) end - def create_customer - Customer.create( - enterprise: distributor, - email: email_for_customer, - user: user, - first_name: bill_address&.first_name.to_s, - last_name: bill_address&.last_name.to_s, - bill_address: bill_address&.clone, - ship_address: ship_address&.clone - ) - end - def ensure_customer self.customer ||= find_customer - self.customer ||= create_customer if require_customer? + self.customer ||= CustomerSyncer.create_customer(self) if require_customer? CustomerSyncer.new(self).synchronise_customer_email end diff --git a/app/services/customer_syncer.rb b/app/services/customer_syncer.rb index 9e0f24b321..3b770d0c93 100644 --- a/app/services/customer_syncer.rb +++ b/app/services/customer_syncer.rb @@ -4,6 +4,18 @@ # # P.S.: I almost couldn't resist to call this CustomerService. class CustomerSyncer + def self.create_customer(order) + Customer.create( + enterprise: order.distributor, + email: (order.user&.email || order.email)&.downcase, + user: order.user, + first_name: order.bill_address&.first_name.to_s, + last_name: order.bill_address&.last_name.to_s, + bill_address: order.bill_address&.clone, + ship_address: order.ship_address&.clone + ) + end + attr_reader :customer, :distributor, :user def initialize(order) From a7de56460db2af35427270efdfa73a06d9698bb9 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Tue, 27 Sep 2022 18:05:31 +1000 Subject: [PATCH 14/15] Further simplify Order by outsourcing to service class --- app/models/spree/order.rb | 11 +---------- app/services/customer_syncer.rb | 11 ++++++++++- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index aaabdcb497..115d8593bd 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -707,17 +707,8 @@ module Spree persisted? && state != "cart" end - def email_for_customer - (user&.email || email)&.downcase - end - - def find_customer - user&.customers&.of(distributor)&.first || - Customer.of(distributor).find_by(email: email_for_customer) - end - def ensure_customer - self.customer ||= find_customer + self.customer ||= CustomerSyncer.find_customer(self) self.customer ||= CustomerSyncer.create_customer(self) if require_customer? CustomerSyncer.new(self).synchronise_customer_email diff --git a/app/services/customer_syncer.rb b/app/services/customer_syncer.rb index 3b770d0c93..35350583ae 100644 --- a/app/services/customer_syncer.rb +++ b/app/services/customer_syncer.rb @@ -4,10 +4,15 @@ # # P.S.: I almost couldn't resist to call this CustomerService. class CustomerSyncer + def self.find_customer(order) + order.user&.customers&.of(order.distributor)&.first || + Customer.of(order.distributor).find_by(email: customer_email(order)) + end + def self.create_customer(order) Customer.create( enterprise: order.distributor, - email: (order.user&.email || order.email)&.downcase, + email: customer_email(order), user: order.user, first_name: order.bill_address&.first_name.to_s, last_name: order.bill_address&.last_name.to_s, @@ -16,6 +21,10 @@ class CustomerSyncer ) end + def self.customer_email(order) + (order.user&.email || order.email)&.downcase + end + attr_reader :customer, :distributor, :user def initialize(order) From 8011d859681945d02be9d56aed8cd3fd714067f0 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 28 Sep 2022 14:23:01 +1000 Subject: [PATCH 15/15] Clarify updating only pre-existing customers --- app/models/spree/order.rb | 4 +-- app/services/customer_syncer.rb | 45 +++++++++++++++------------------ 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb index 115d8593bd..2c2df175cd 100644 --- a/app/models/spree/order.rb +++ b/app/models/spree/order.rb @@ -708,10 +708,8 @@ module Spree end def ensure_customer - self.customer ||= CustomerSyncer.find_customer(self) + self.customer ||= CustomerSyncer.find_and_update_customer(self) self.customer ||= CustomerSyncer.create_customer(self) if require_customer? - - CustomerSyncer.new(self).synchronise_customer_email end def update_adjustment!(adjustment) diff --git a/app/services/customer_syncer.rb b/app/services/customer_syncer.rb index 35350583ae..f97b845c64 100644 --- a/app/services/customer_syncer.rb +++ b/app/services/customer_syncer.rb @@ -4,11 +4,32 @@ # # P.S.: I almost couldn't resist to call this CustomerService. class CustomerSyncer + def self.find_and_update_customer(order) + find_customer(order).tap { |customer| synchronise_email(order, customer) } + end + def self.find_customer(order) order.user&.customers&.of(order.distributor)&.first || Customer.of(order.distributor).find_by(email: customer_email(order)) end + def self.synchronise_email(order, customer) + email = order.user&.email + + return unless email && customer && email != customer.email + + duplicate = Customer.find_by(email: email, enterprise: order.distributor) + + if duplicate.present? + Spree::Order.where(customer_id: duplicate.id).update_all(customer_id: customer.id) + Subscription.where(customer_id: duplicate.id).update_all(customer_id: customer.id) + + duplicate.destroy + end + + customer.update(email: email) + end + def self.create_customer(order) Customer.create( enterprise: order.distributor, @@ -24,28 +45,4 @@ class CustomerSyncer def self.customer_email(order) (order.user&.email || order.email)&.downcase end - - attr_reader :customer, :distributor, :user - - def initialize(order) - @customer = order.customer - @distributor = order.distributor - @user = order.user - end - - # Update the customer record if the user changed their email address. - def synchronise_customer_email - return unless user && customer && user.email != customer.email - - duplicate = Customer.find_by(email: user.email, enterprise: distributor) - - if duplicate.present? - Spree::Order.where(customer_id: duplicate.id).update_all(customer_id: customer.id) - Subscription.where(customer_id: duplicate.id).update_all(customer_id: customer.id) - - duplicate.destroy - end - - customer.update(email: user.email) - end end