diff --git a/lib/spree/core/product_duplicator.rb b/lib/spree/core/product_duplicator.rb index 5000caf7cd..c36c934ea3 100644 --- a/lib/spree/core/product_duplicator.rb +++ b/lib/spree/core/product_duplicator.rb @@ -32,9 +32,12 @@ module Spree end def duplicate_variants - product.variants.map do |variant| + # Create a hash with mapping: { : , } + mapped_variants = product.variants.index_with do |variant| duplicate_variant(variant) end + duplicate_variant_links(mapped_variants) + mapped_variants.values end def duplicate_variant(variant) @@ -47,6 +50,19 @@ module Spree end end + def duplicate_variant_links(mapped_variants) + # Find any links between orig variants (links to/from another product are ignored) + variant_links = VariantLink.where(source_variant: [mapped_variants.keys], + target_variant: [mapped_variants.keys]) + # Link the new variants + variant_links.find_each do |variant_link| + VariantLink.create( + source_variant: mapped_variants[variant_link.source_variant], + target_variant: mapped_variants[variant_link.target_variant] + ) + end + end + def duplicate_image(image) new_image = image.dup new_image.attachment.attach(image.attachment_blob) diff --git a/spec/lib/spree/core/product_duplicator_spec.rb b/spec/lib/spree/core/product_duplicator_spec.rb index 5f22636065..89bd582ffa 100644 --- a/spec/lib/spree/core/product_duplicator_spec.rb +++ b/spec/lib/spree/core/product_duplicator_spec.rb @@ -36,6 +36,7 @@ RSpec.describe Spree::Core::ProductDuplicator do it "can duplicate a product" do duplicator = Spree::Core::ProductDuplicator.new(product) + allow(duplicator).to receive(:duplicate_variant_links) # tested elsewhere expect(new_product).to receive(:name=).with("COPY OF foo") expect(new_product).to receive(:sku=).with("") expect(new_product).to receive(:product_properties=).with([new_property]) @@ -65,6 +66,29 @@ RSpec.describe Spree::Core::ProductDuplicator do end end + describe "duplicating" do + subject { described_class.new(product).duplicate } + context "with variant links" do + let!(:product) { create(:product) } + let!(:source_variant) { product.variants.first } + let!(:linked_variant1) { source_variant.create_linked_variant(source_variant.supplier.owner) } + let!(:linked_variant2) { source_variant.create_linked_variant(source_variant.supplier.owner) } + + it "duplicates variant links" do + expect(subject).to be_a Spree::Product + expect(subject.variants.count).to eq 3 + + # assuming they are cloned in the same order + new_source_variant = subject.variants[0] + new_linked_variant1 = subject.variants[1] + new_linked_variant2 = subject.variants[2] + expect(new_source_variant.target_variants).to eq [new_linked_variant1, new_linked_variant2] + expect(new_linked_variant1.source_variants).to eq [new_source_variant] + expect(new_linked_variant2.source_variants).to eq [new_source_variant] + end + end + end + describe "errors" do context "with invalid product" do # Name has a max length of 255 char, when cloning a product the cloned product has a name