Skip to content

Commit

Permalink
Backport promotion code batch fix from Solidus
Browse files Browse the repository at this point in the history
Backport Solidus PR 5383 with PR description:

When a new promotion with 2.5m new promo codes has created, it just generated about 250k promo codes and then stopped.

The PromotionBatch screen this error: Errored: #<ActiveRecord::RecordInvalid: Validation failed: Value has already been taken>

This PR rescues the exception raised by the Spree::PromotionCode creation and jumps to the next code to save, avoiding stopping the process completely.
The PR also adds the ability to restart the PromotionCodeBatch from the latest PromotionCodes created.

Co-Authored-By: Daniele Palombo
  • Loading branch information
mamhoff committed Oct 27, 2023
1 parent 92f05b6 commit 483927f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,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
Expand All @@ -42,13 +43,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|
PromotionCode.create!(
codes_for_current_batch = codes_for_current_batch.map do |value|
SolidusFriendlyPromotions::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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,34 @@
end
end
end

context "when promotion_code creation returns an error" do
before do
@raise_exception = true
allow(SolidusFriendlyPromotions::PromotionCode).to receive(:create!) do
if @raise_exception
@raise_exception = false
raise(ActiveRecord::RecordInvalid)
else
create(:friendly_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
let(:number_of_codes) { 50 }
before do
create_list(:friendly_promotion_code, 11, promotion: promotion, promotion_code_batch: 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

0 comments on commit 483927f

Please sign in to comment.