Skip to content

Implement custom registration transfer logic while merging#14101

Draft
danieljames-dj wants to merge 2 commits intothewca:mainfrom
danieljames-dj:reg-merge
Draft

Implement custom registration transfer logic while merging#14101
danieljames-dj wants to merge 2 commits intothewca:mainfrom
danieljames-dj:reg-merge

Conversation

@danieljames-dj
Copy link
Copy Markdown
Member

This change is because currently if we try to merge two users having registrations at same competition, it fails.

Comment thread app/models/user.rb
Comment on lines +1584 to +1600
# 2. Handle conflicting registrations (where both users registered for the same competition):
# - If both are accepted: Raise error.
# - If only incoming is accepted: Swap them so the master account gets the accepted one.
# - Otherwise (incoming is not accepted): Keep the master's and the other stays in the old account.
registrations.where(competition_id: to_user_competition_ids).find_each do |registration|
other_registration = new_user.registrations.find_by(competition_id: registration.competition_id)
if registration.accepted? && other_registration.accepted?
raise "Both users have accepted registrations for #{registration.competition.name} (#{registration.competition_id})"
elsif registration.accepted?
# The master account has a non-accepted registration, but the old account has an accepted one.
# We swap them: the master gets the accepted one, and the old account keeps the unaccepted one.
# We use update_columns to bypass validations and avoid intermediate unique index violations.
other_registration.update_columns(user_id: nil)
registration.update_columns(user_id: new_user.id)
other_registration.update_columns(user_id: id)
end
end
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you focus on the status accepted so much? I have not thought through all corner-cases, so maybe I'm missing something, but at least from a high-level standpoint it should be enough to:

  1. Update all non-conflicting registrations (you're already doing that above)
  2. For all conflicting registrations:
    1. Update either one to rejected
    2. Leave the other on accepted

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of coding shenanigans, you should take a step back and think about what is the desired goal here from a business logic perspective.

The scenario you're trying to solve/fix when the same (phyiscal) person registers twice for the same competition. What if, for example, both registrations have been paid for via Stripe? In that case, we must definitely keep both registrations in our database, to keep the payment history. But which one (the old, to-be-ignored user or the new, after-merge-winner user) should be the one that actually counts as "going to the competition"?

  • What if both registrations have a different selection of events?
  • What if one has an admin comment and the other does not?
  • etc...

These questions should be solved from a non-code business logic perspective first, and then you can find a clever way to do this in code.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm looks like my solution is actually not solving the full problem, it's not considering the cases that you mentioned. I'll mark this PR as draft and post in the group for discussion.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I'm not posting this in group now, but I'll think through it again later and try if I can think of a solution.

The problem here is that we need to select one of the two (or even more) registrations. In my solution, the reason why I considered current registration as 'master' registration is because the results and events will be more accurate with current registration.

Reason why I was not happy with two accepted registration was because there are chances that one of the twins will have the WCA ID, and the delegate might wrongly assume they are same, and click 'merge'.

Does this answer your questions or do you still see a gap?

I understand there can be admin comment on the non-accepted registration, but should we care about it because that is going to stay unaccepted, as we are swapping user?

Comment thread app/models/user.rb
elsif registration.accepted?
# The master account has a non-accepted registration, but the old account has an accepted one.
# We swap them: the master gets the accepted one, and the old account keeps the unaccepted one.
# We use update_columns to bypass validations and avoid intermediate unique index violations.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "trick" with update_columns does not work because the uniqueness validation exists on a pure database level. update_columns only bypasses Rails model validations, but the SQL UNIQUE index will still complain.

@danieljames-dj danieljames-dj marked this pull request as draft April 26, 2026 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants