diff --git a/core/app/models/spree/promotion_code/batch_builder.rb b/core/app/models/spree/promotion_code/batch_builder.rb index 26fa1d63745..0b8c80a532a 100644 --- a/core/app/models/spree/promotion_code/batch_builder.rb +++ b/core/app/models/spree/promotion_code/batch_builder.rb @@ -30,7 +30,8 @@ def build_promotion_codes private def generate_random_codes - created_codes = 0 + created_codes = promotion_code_batch.promotion_codes.count + batch_size = @options[:batch_size] while created_codes < number_of_codes @@ -39,13 +40,15 @@ def generate_random_codes new_codes = Array.new(max_codes_to_generate) { generate_random_code }.uniq codes_for_current_batch = get_unique_codes(new_codes) - codes_for_current_batch.each do |value| + codes_for_current_batch = codes_for_current_batch.map do |value| Spree::PromotionCode.create!( value: value, promotion: promotion, promotion_code_batch: promotion_code_batch ) - end + rescue ActiveRecord::RecordInvalid + nil + end.compact created_codes += codes_for_current_batch.size end end diff --git a/core/spec/models/spree/promotion_code/batch_builder_spec.rb b/core/spec/models/spree/promotion_code/batch_builder_spec.rb index 67e513ba11b..7b52fffe859 100644 --- a/core/spec/models/spree/promotion_code/batch_builder_spec.rb +++ b/core/spec/models/spree/promotion_code/batch_builder_spec.rb @@ -72,6 +72,35 @@ subject.build_promotion_codes expect(promotion.codes.size).to eq(number_of_codes) end + + context "when promotion_code creation returns an error" do + before do + @raise_exception = true + allow(Spree::PromotionCode).to receive(:create!) do + if @raise_exception + @raise_exception = false + raise(ActiveRecord::RecordInvalid) + else + create(:promotion_code, promotion: promotion) + end + end + end + + it "creates the correct number of codes anyway" do + subject.build_promotion_codes + expect(promotion.codes.size).to eq(number_of_codes) + end + end + + context "when same promotion_codes are already present" do + before do + create_list(:promotion_code, 11, promotion: promotion, promotion_code_batch: promotion_code_batch) + end + + it "creates only the missing promotion_codes" do + expect { subject.build_promotion_codes }.to change { promotion.codes.size }.by(39) + end + end end end