Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Plugins/org.secc.FamilyCheckin/Workflows/SaveAttendance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,11 @@ public override bool Execute( RockContext rockContext, Rock.Model.WorkflowAction
}
};

attendanceService.Add( attendance );
// NOTE: Do not call attendanceService.Add( attendance ) here. AddOrUpdate already
// adds new records to the context. When AddOrUpdate returns an EXISTING attendance
// (same person + occurrence), calling Add would flip the tracked entity's state to
// Added, causing EF to INSERT a duplicate row and silently drop the update that
// closed the old attendance — the double check-in bug (ROCK-8700).
attendances.Add( attendance );
}
}
Expand Down
7 changes: 7 additions & 0 deletions Plugins/org.secc.RoomScanner/Utilities/DataHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ public static void CloneAttendance( Attendance attendance, bool isSubroom, Locat
{
newAttendance.ForeignId = null;
}
// NOTE (ROCK-8700): This Add looks redundant (AddOrUpdate already adds new records), but it is
// intentional here. When AddOrUpdate returns an EXISTING attendance row (e.g. subroom scan where
// the target occurrence matches the source attendance's occurrence), Add flips the tracked entity
// to Added so EF INSERTs a fresh row — that new row is the "clone", while the source attendance
// (tracked by the caller's context) is closed below/by the caller. Removing this Add would cause
// the same row to be reopened and then closed, checking the person out instead of moving them.
// This is safe here because the source row is always closed afterward, so only one row stays active.
attendanceService.Add( newAttendance );
var stayedFifteenMinutes = ( Rock.RockDateTime.Now - attendance.StartDateTime ) > new TimeSpan( 0, 15, 0 );
attendance.DidAttend = stayedFifteenMinutes;
Expand Down