diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb index 6e9e04607f..ce1846cf54 100644 --- a/app/models/order_cycle.rb +++ b/app/models/order_cycle.rb @@ -168,24 +168,7 @@ class OrderCycle < ApplicationRecord end def clone! - oc = dup - oc.name = I18n.t("models.order_cycle.cloned_order_cycle_name", order_cycle: oc.name) - oc.orders_open_at = oc.orders_close_at = oc.mails_sent = oc.processed_at = nil - oc.coordinator_fee_ids = coordinator_fee_ids - # rubocop:disable Layout/LineLength - oc.preferred_product_selection_from_coordinator_inventory_only = preferred_product_selection_from_coordinator_inventory_only - # rubocop:enable Layout/LineLength - oc.schedule_ids = schedule_ids - oc.save! - exchanges.each { |e| e.clone!(oc) } - oc.selected_distributor_payment_method_ids = ( - attachable_distributor_payment_methods.map(&:id) & selected_distributor_payment_method_ids - ) - oc.selected_distributor_shipping_method_ids = ( - attachable_distributor_shipping_methods.map(&:id) & selected_distributor_shipping_method_ids - ) - sync_subscriptions - oc.reload + OrderCycleClone.new(self).create end def variants diff --git a/app/services/order_cycle_clone.rb b/app/services/order_cycle_clone.rb new file mode 100644 index 0000000000..1821d26d71 --- /dev/null +++ b/app/services/order_cycle_clone.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'order_management/subscriptions/proxy_order_syncer' + +class OrderCycleClone + def initialize(order_cycle) + @original_order_cycle = order_cycle + end + + def create + oc = @original_order_cycle.dup + oc.name = I18n.t("models.order_cycle.cloned_order_cycle_name", order_cycle: oc.name) + oc.orders_open_at = oc.orders_close_at = oc.mails_sent = oc.processed_at = nil + oc.coordinator_fee_ids = @original_order_cycle.coordinator_fee_ids + # rubocop:disable Layout/LineLength + oc.preferred_product_selection_from_coordinator_inventory_only = @original_order_cycle.preferred_product_selection_from_coordinator_inventory_only + # rubocop:enable Layout/LineLength + oc.schedule_ids = @original_order_cycle.schedule_ids + oc.save! + @original_order_cycle.exchanges.each { |e| e.clone!(oc) } + oc.selected_distributor_payment_method_ids = selected_distributor_payment_method_ids + oc.selected_distributor_shipping_method_ids = selected_distributor_shipping_method_ids + sync_subscriptions + oc.reload + end + + private + + def selected_distributor_payment_method_ids + @original_order_cycle.attachable_distributor_payment_methods.map(&:id) & + @original_order_cycle.selected_distributor_payment_method_ids + end + + def selected_distributor_shipping_method_ids + @original_order_cycle.attachable_distributor_shipping_methods.map(&:id) & + @original_order_cycle.selected_distributor_shipping_method_ids + end + + def sync_subscriptions + return unless @original_order_cycle.schedule_ids.any? + + OrderManagement::Subscriptions::ProxyOrderSyncer.new( + Subscription.where(schedule_id: @original_order_cycle.schedule_ids) + ).sync! + end +end diff --git a/spec/models/order_cycle_spec.rb b/spec/models/order_cycle_spec.rb index a890d68e9a..818b900e19 100644 --- a/spec/models/order_cycle_spec.rb +++ b/spec/models/order_cycle_spec.rb @@ -368,93 +368,6 @@ describe OrderCycle do end end - describe "clone!" do - it "clones itself" do - coordinator = create(:enterprise); - oc = create(:simple_order_cycle, - coordinator_fees: [create(:enterprise_fee, enterprise: coordinator)], - preferred_product_selection_from_coordinator_inventory_only: true, - automatic_notifications: true, processed_at: Time.zone.now, mails_sent: true) - schedule = create(:schedule, order_cycles: [oc]) - ex1 = create(:exchange, order_cycle: oc) - ex2 = create(:exchange, order_cycle: oc) - oc.clone! - - occ = OrderCycle.last - expect(occ.name).to eq("COPY OF #{oc.name}") - expect(occ.orders_open_at).to be_nil - expect(occ.orders_close_at).to be_nil - expect(occ.coordinator).not_to be_nil - expect(occ.preferred_product_selection_from_coordinator_inventory_only).to be true - expect(occ.automatic_notifications).to eq(oc.automatic_notifications) - expect(occ.processed_at).to eq(nil) - expect(occ.mails_sent).to eq(nil) - expect(occ.coordinator).to eq(oc.coordinator) - - expect(occ.coordinator_fee_ids).not_to be_empty - expect(occ.coordinator_fee_ids).to eq(oc.coordinator_fee_ids) - expect(occ.preferred_product_selection_from_coordinator_inventory_only).to eq(oc.preferred_product_selection_from_coordinator_inventory_only) - expect(occ.schedule_ids).not_to be_empty - expect(occ.schedule_ids).to eq(oc.schedule_ids) - - # Check that the exchanges have been cloned. - original_exchange_attributes = oc.exchanges.map { |ex| core_exchange_attributes(ex) } - cloned_exchange_attributes = occ.exchanges.map { |ex| core_exchange_attributes(ex) } - - expect(cloned_exchange_attributes).to match_array original_exchange_attributes - end - - context "when it has selected payment methods which can longer be applied validly - e.g. payment method is backoffice only" do - it "only attaches the valid ones to the clone" do - distributor = create(:distributor_enterprise) - distributor_payment_method_i = create( - :payment_method, - distributors: [distributor] - ).distributor_payment_methods.first - distributor_payment_method_ii = create( - :payment_method, - distributors: [distributor], - display_on: "back_end" - ).distributor_payment_methods.first - order_cycle = create(:distributor_order_cycle, distributors: [distributor]) - order_cycle.selected_distributor_payment_methods = [ - distributor_payment_method_i, - distributor_payment_method_ii - ] - - cloned_order_cycle = order_cycle.clone! - - expect(cloned_order_cycle.distributor_payment_methods).to eq [distributor_payment_method_i] - end - end - - context "when it has selected shipping methods which can longer be applied validly - e.g. shipping method is backoffice only" do - it "only attaches the valid ones to the clone" do - distributor = create(:distributor_enterprise) - distributor_shipping_method_i = create( - :shipping_method, - distributors: [distributor] - ).distributor_shipping_methods.first - distributor_shipping_method_ii = create( - :shipping_method, - distributors: [distributor], - display_on: Spree::ShippingMethod::DISPLAY_ON_OPTIONS[:back_end] - ).distributor_shipping_methods.first - order_cycle = create(:distributor_order_cycle, distributors: [distributor]) - order_cycle.selected_distributor_shipping_methods = [ - distributor_shipping_method_i, - distributor_shipping_method_ii - ] - - cloned_order_cycle = order_cycle.clone! - - expect(cloned_order_cycle.distributor_shipping_methods).to eq [distributor_shipping_method_i] - end - end - end - describe "finding recently closed order cycles" do it "should give the most recently closed order cycle for a distributor" do distributor = create(:distributor_enterprise) @@ -867,14 +780,4 @@ describe OrderCycle do expect(order_cycle).not_to be_simple end end - - def core_exchange_attributes(exchange) - exterior_attribute_keys = %w(id order_cycle_id created_at updated_at) - exchange.attributes. - reject { |k| exterior_attribute_keys.include? k }. - merge( - 'variant_ids' => exchange.variant_ids.sort, - 'enterprise_fee_ids' => exchange.enterprise_fee_ids.sort - ) - end end diff --git a/spec/services/order_cycle_clone_spec.rb b/spec/services/order_cycle_clone_spec.rb new file mode 100644 index 0000000000..7779b19da3 --- /dev/null +++ b/spec/services/order_cycle_clone_spec.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe OrderCycleForm do + describe "#create" do + it "clones the order cycle" do + coordinator = create(:enterprise); + oc = create(:simple_order_cycle, + coordinator_fees: [create(:enterprise_fee, enterprise: coordinator)], + preferred_product_selection_from_coordinator_inventory_only: true, + automatic_notifications: true, processed_at: Time.zone.now, mails_sent: true) + schedule = create(:schedule, order_cycles: [oc]) + ex1 = create(:exchange, order_cycle: oc) + ex2 = create(:exchange, order_cycle: oc) + + occ = OrderCycleClone.new(oc).create + expect(occ.name).to eq("COPY OF #{oc.name}") + expect(occ.orders_open_at).to be_nil + expect(occ.orders_close_at).to be_nil + expect(occ.coordinator).not_to be_nil + expect(occ.preferred_product_selection_from_coordinator_inventory_only).to be true + expect(occ.automatic_notifications).to eq(oc.automatic_notifications) + expect(occ.processed_at).to eq(nil) + expect(occ.mails_sent).to eq(nil) + expect(occ.coordinator).to eq(oc.coordinator) + + expect(occ.coordinator_fee_ids).not_to be_empty + expect(occ.coordinator_fee_ids).to eq(oc.coordinator_fee_ids) + expect(occ.preferred_product_selection_from_coordinator_inventory_only).to eq( + oc.preferred_product_selection_from_coordinator_inventory_only + ) + expect(occ.schedule_ids).not_to be_empty + expect(occ.schedule_ids).to eq(oc.schedule_ids) + + # Check that the exchanges have been cloned. + original_exchange_attributes = oc.exchanges.map { |ex| core_exchange_attributes(ex) } + cloned_exchange_attributes = occ.exchanges.map { |ex| core_exchange_attributes(ex) } + + expect(cloned_exchange_attributes).to match_array original_exchange_attributes + end + + context "when it has selected payment methods which can longer be applied validly + e.g. payment method is backoffice only" do + it "only attaches the valid ones to the clone" do + distributor = create(:distributor_enterprise) + distributor_payment_method_i = create( + :payment_method, + distributors: [distributor] + ).distributor_payment_methods.first + distributor_payment_method_ii = create( + :payment_method, + distributors: [distributor], + display_on: "back_end" + ).distributor_payment_methods.first + order_cycle = create(:distributor_order_cycle, distributors: [distributor]) + order_cycle.selected_distributor_payment_methods = [ + distributor_payment_method_i, + distributor_payment_method_ii + ] + + cloned_order_cycle = order_cycle.clone! + + expect(cloned_order_cycle.distributor_payment_methods).to eq [distributor_payment_method_i] + end + end + + context "when it has selected shipping methods which can longer be applied validly + e.g. shipping method is backoffice only" do + it "only attaches the valid ones to the clone" do + distributor = create(:distributor_enterprise) + distributor_shipping_method_i = create( + :shipping_method, + distributors: [distributor] + ).distributor_shipping_methods.first + distributor_shipping_method_ii = create( + :shipping_method, + distributors: [distributor], + display_on: Spree::ShippingMethod::DISPLAY_ON_OPTIONS[:back_end] + ).distributor_shipping_methods.first + order_cycle = create(:distributor_order_cycle, distributors: [distributor]) + order_cycle.selected_distributor_shipping_methods = [ + distributor_shipping_method_i, + distributor_shipping_method_ii + ] + + cloned_order_cycle = order_cycle.clone! + + expect(cloned_order_cycle.distributor_shipping_methods).to eq [ + distributor_shipping_method_i + ] + end + end + end + + private + + def core_exchange_attributes(exchange) + exterior_attribute_keys = %w(id order_cycle_id created_at updated_at) + exchange.attributes. + reject { |k| exterior_attribute_keys.include? k }. + merge( + 'variant_ids' => exchange.variant_ids.sort, + 'enterprise_fee_ids' => exchange.enterprise_fee_ids.sort + ) + end +end