diff --git a/app/models/spree_cm_commissioner/guest.rb b/app/models/spree_cm_commissioner/guest.rb index 1c795a8af..29ac87870 100644 --- a/app/models/spree_cm_commissioner/guest.rb +++ b/app/models/spree_cm_commissioner/guest.rb @@ -180,23 +180,22 @@ def bib_display_prefix? end def generate_bib - return if bib_prefix.present? - return unless bib_required? - return if event_id.blank? + return if bib_prefix.present? || !bib_required? || event_id.blank? - self.bib_prefix = line_item.variant.bib_prefix + self.class.transaction do + rows = self.class.where(event_id: event_id, bib_prefix: line_item.variant.bib_prefix).lock + last_bib_number = rows.map(&:bib_number).max || 0 - last_bib_number = event.guests - .where(bib_prefix: bib_prefix) - .maximum(:bib_number) || 0 + self.bib_prefix = line_item.variant.bib_prefix + self.bib_number = last_bib_number + 1 + self.bib_index = "#{event_id}-#{bib_prefix}-#{bib_number}" - self.bib_number = last_bib_number + 1 - self.bib_index = "#{event_id}-#{bib_prefix}-#{bib_number}" + save! + end end def generate_bib! generate_bib - save! end # bib_number: 345, bib_prefix: 5KM, bib_zerofill: 5 => return 5KM00345 diff --git a/spec/models/spree_cm_commissioner/guest_spec.rb b/spec/models/spree_cm_commissioner/guest_spec.rb index 89aa06990..9318aff49 100644 --- a/spec/models/spree_cm_commissioner/guest_spec.rb +++ b/spec/models/spree_cm_commissioner/guest_spec.rb @@ -309,7 +309,6 @@ end end - context "when guest in the same event" do context "when guest has the same prefix" do let(:line_item) { create(:line_item, order: order, variant: product_with_bib1.variants.first) } @@ -327,6 +326,23 @@ end end + context "when multiple generate_bib! concurrently" do + let(:line_item) { create(:line_item, order: order, variant: product_with_bib1.variants.first) } + let(:guest1) { create(:guest, line_item: line_item, seat_number: 1) } + let(:guest2) { create(:guest, line_item: line_item, seat_number: 2) } + let(:bib_prefix) { line_item.variant.bib_prefix } + + it 'ensures unique bib_numbers and bib_index for each guest' do + threads = [] + threads << Thread.new { guest1.generate_bib! } + threads << Thread.new { guest2.generate_bib! } + threads.each(&:join) + + bib_indices = SpreeCmCommissioner::Guest.where(event_id: guest1.event_id, bib_prefix: bib_prefix).pluck(:bib_index) + expect(bib_indices.uniq.size).to eq(2) + end + end + context "when guest has different prefix" do let(:line_item1) { create(:line_item, order: order, variant: product_with_bib1.variants.first) } let(:line_item2) { create(:line_item, order: order, variant: product_with_bib1.variants.last) }