feat(invitations): complete external ID bulk invite flow and redesign result dialog#8406
Draft
LWS49 wants to merge 1 commit into
Draft
feat(invitations): complete external ID bulk invite flow and redesign result dialog#8406LWS49 wants to merge 1 commit into
LWS49 wants to merge 1 commit into
Conversation
0227e24 to
c0dcc05
Compare
… result dialog Ext ID is now accepted in bulk invite CSVs. For existing enrolled users and pending invitations, if external ID is provided, it upserts the current external ID. Conflicts due to duplicate emails or external IDs route to Needs Attention, with clear reasons explaining what to be done.
c0dcc05 to
e892fd9
Compare
|
|
||
| context 'when an existing course user has non-nil ext_id and CSV provides a free different value' do | ||
| it 'updates the course_user external_id' do | ||
| result = subject.invite(enrolled_conflict_user_attrs) |
There was a problem hiding this comment.
Lint/UselessAssignment: Useless assignment to variable - result.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes the external ID bulk invite flow started in the previous PR. The CSV upload now acts as a full upsert for external IDs on existing records: a nil ext_id is filled in, a non-nil ext_id that differs from the CSV value is overwritten (not rejected), and a blank CSV cell preserves the existing value. The
external_id_conflicterror condition is removed - the only remaining hard rejection for ext_id isexternal_id_taken(the CSV value is already held by a different course member). The invite result dialog is redesigned: six conditional flat sections replace the previous accordion layout, updated rows fold into the Existing Invitations and Existing Course Users sections with a bold ext_id and old-value tooltip, and the separate "External IDs Updated" section is removed.Design decisions
external_id_conflicttreated as upsert, not error - CSV uploads are submitted exclusively by course staff (trusted actors). The real safety guard isexternal_id_taken(ID collision across different people), which is still a hard error. Flagging a staff member correcting a previous ext_id entry as a conflict imposes workflow cost with no safety gain beyond whatexternal_id_takenalready provides. Nil→value and non-nil→different-value are now treated symmetrically.freed-idtonew-idand Bob claimsfreed-idin the same batch, Alice's update must persist first so Bob's insert doesn't hit the unique constraint.Cross-type freed-ID ordering note
When an existing course user frees an ext_id and a brand-new user (no existing Coursemology account) claims it in the same batch, the new user is still rejected with
external_id_taken. This is becauseinvite_new_usersruns beforeadd_existing_usersin the processing pipeline, so the new invitation is evaluated before the existing course user releases the ID. This is a known ordering limitation documented in the spec (test: document cross-type freed-id ordering behavior). The same-type freed-ID case (both are existing invitations, or both are existing course users) works correctly.Regression prevention
Specs cover: nil→value upsert for invitations and course users; non-nil→different-free-value upsert with
previous_external_idcapture;external_id_takenstill fires when the target ID is held by another member; freed-ID batch claim within the same record type; cross-type freed-ID ordering behavior (documented as a known limitation);previousExternalIdrendered in Jbuilder response.Frontend tests cover:
InvitationResultSkippedTableupdated-row rendering (bold + badge + tooltip);InvitationResultDialogupdated rows appear in Existing Invitations section, no "External IDs Updated" heading;InvitationResultUsersTablereason text assertions for all three remaining duplicate reasons.Manual testing: all 7 scenarios above verified - happy path new batch, nil→value upsert with badge, non-nil→different upsert with tooltip,
external_id_takenNeeds Attention, freed-ID same-type batch, existing user no-change, dialog layout with no External IDs Updated section.Backward compatibility: existing invite flows unaffected. The only behavioral change for existing data is that re-inviting a user whose ext_id differs from the CSV value now updates the record instead of rejecting it.