From 45f1f0f880b6151ca336810b15d41c5302a2a045 Mon Sep 17 00:00:00 2001 From: neuroalien <105230050+neuroalien@users.noreply.github.com> Date: Thu, 22 Jan 2026 03:28:52 +0000 Subject: [PATCH] AO3-5748 Split off assignments with both offer and pinch hitter Usually, when a mod assigns a pinch-hitter through other means, a brand new ChallengeAssignment is created with a pinch_hitter_id (rather than adding a pinch_hitter_id to the existing ChallengeAssignment). Let's do the same for the case of a pinch hitter being assigned at the same time as the offer signup. We've chosen to do this at the point of saving the current configuration, so we can show the resulting assignments. We hope the maintainer won't double-assign again, thus causing a chain of splits. I've chosen to do this in a separate method, invoked after `update_placeholder_assignments!` has done its thing, because otherwise our freshly created assignment would have been deleted as being a "leftover placeholder" by the "# if this signup has at least one giver now, get rid of any leftover placeholders" check. I didn't want to mess with how leftover placeholders are defined, since we don't have any open issues about them. --- .../challenge_assignments_controller.rb | 1 + app/models/challenge_assignment.rb | 20 +++++++++++++ .../challenge_assignments_controller_spec.rb | 30 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/app/controllers/challenge_assignments_controller.rb b/app/controllers/challenge_assignments_controller.rb index b382c2e2691..e59c727cb89 100644 --- a/app/controllers/challenge_assignments_controller.rb +++ b/app/controllers/challenge_assignments_controller.rb @@ -149,6 +149,7 @@ def set end ChallengeAssignment.update_placeholder_assignments!(@collection) + ChallengeAssignment.split_off_write_in_giver_assignments!(@collection) if @assignments.empty? flash[:notice] = "Assignments updated" redirect_to collection_potential_matches_path(@collection) diff --git a/app/models/challenge_assignment.rb b/app/models/challenge_assignment.rb index 347473b8b06..cdedd71f656 100755 --- a/app/models/challenge_assignment.rb +++ b/app/models/challenge_assignment.rb @@ -496,4 +496,24 @@ def self.update_placeholder_assignments!(collection) end end end + + # create fresh new assignments for pinch hitters assigned alongside existing offer signups + def self.split_off_write_in_giver_assignments!(collection) + collection.assignments.each do |assignment| + assignment.split if assignment.double_assigned? + end + end + + def double_assigned? + pinch_hitter && offer_signup && pinch_hitter.user != offering_user + end + + def split + new_assignment = self.dup + new_assignment.offer_signup = nil + new_assignment.save! + + self.pinch_hitter = nil + save! + end end diff --git a/spec/controllers/challenge_assignments_controller_spec.rb b/spec/controllers/challenge_assignments_controller_spec.rb index 3e87664965e..5eb26a1677a 100644 --- a/spec/controllers/challenge_assignments_controller_spec.rb +++ b/spec/controllers/challenge_assignments_controller_spec.rb @@ -146,6 +146,36 @@ end end + context "when an assignment has both an offer and a pinch hitter" do + let(:params) do + { + collection_id: collection.name, + challenge_assignments: { + assignment.id => { + request_signup_pseud: signup1.pseud.byline, + offer_signup_pseud: signup2.pseud.byline, + pinch_hitter_byline: other_user.pseuds.first.byline + } + } + } + end + + it "creates a new assignment for the pinch hitter" do + PotentialMatch.create(request_signup: signup1, + offer_signup: signup2, + collection: collection) + + put :set, params: params + + assignment.reload + expect(assignment.pinch_hitter).to be_nil + + pinch_hitter_assignment = collection.assignments.find_by(pinch_hitter_id: other_user.pseuds.first.id) + expect(pinch_hitter_assignment).to be_present + expect(pinch_hitter_assignment.offer_signup).to be_nil + end + end + context "when assignments have been sent" do let(:gift_exchange) { create(:gift_exchange, assignments_sent_at: Faker::Time.backward) }