From 299ada1220ccd5520f333cada4155cede5b5975f Mon Sep 17 00:00:00 2001 From: David Cook Date: Wed, 4 Mar 2026 12:35:13 +1100 Subject: [PATCH] Refactor: move variant duplication to model I tried to avoid it but rubocop made me move it. I think maybe it will need to go into a concern or service class later, but hopefully it's ok here for now. --- .../admin/products_v3_controller.rb | 10 +------ app/models/spree/variant.rb | 18 +++++++++++ spec/models/spree/variant_spec.rb | 30 +++++++++++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/app/controllers/admin/products_v3_controller.rb b/app/controllers/admin/products_v3_controller.rb index 9dbafeb7ce..073107c15e 100644 --- a/app/controllers/admin/products_v3_controller.rb +++ b/app/controllers/admin/products_v3_controller.rb @@ -116,15 +116,7 @@ module Admin status = :ok begin - variant = source_variant.dup #may need a VariantDuplicator like producs? - variant.price = source_variant.price - variant.save! - variant.source_variants << source_variant - # Owner is my enterprise which has permission to create sourced variants from that supplier - variant.owner_id = EnterpriseRelationship.permitted_by(source_variant.supplier).permitting(spree_current_user.enterprises).with_permission(:create_sourced_variants).pluck(:child_id).first - variant.on_demand = source_variant.on_demand - variant.on_hand = source_variant.on_hand - variant.save! + variant = source_variant.create_sourced_variant(spree_current_user) flash.now[:success] = t('.success') variant_index = "-#{variant.id}" diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index 8276164fbc..952f48d23d 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -273,6 +273,24 @@ module Spree @on_hand_desired = ActiveModel::Type::Integer.new.cast(val) end + # Clone this variant, retaining a 'source' link to it + def create_sourced_variant(user) + # Owner is my enterprise which has permission to create sourced variants from that supplier + owner_id = EnterpriseRelationship.permitted_by(supplier).permitting(user.enterprises) + .with_permission(:create_sourced_variants) + .pick(:child_id) + + dup.tap do |variant| + variant.price = price + variant.save! + variant.source_variants = [self] + variant.owner_id = owner_id + variant.on_demand = on_demand + variant.on_hand = on_hand + variant.save! + end + end + private def check_currency diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 38655f5f1f..a53b3f533b 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -1005,4 +1005,34 @@ RSpec.describe Spree::Variant do expect(variant.unit_presentation).to eq "My display" end end + + describe "#create_sourced_variant" do + let(:user) { create(:user, enterprises: [enterprise]) } + let(:supplier) { variant.supplier } + let(:enterprise) { create(:enterprise) } + + context "with create_sourced_variants permissions on supplier" do + let!(:enterprise_relationship) { + create(:enterprise_relationship, + parent: supplier, + child: enterprise, + permissions_list: [:create_sourced_variants]) + } + + it "clones the variant, retaining a link to the source" do + variant.price = 10.95 + variant.save! + variant.on_demand = false + variant.on_hand = 5 + + sourced_variant = variant.create_sourced_variant(user) + + expect(sourced_variant.source_variants).to eq [variant] + expect(sourced_variant.owner).to eq enterprise + expect(sourced_variant.price).to eq 10.95 + expect(sourced_variant.on_demand).to eq false + expect(sourced_variant.on_hand).to eq 5 + end + end + end end