feat: implement recording stats update mechanism for auto-matching

Add automatic tracking of recording statistics (recordingsDone/recordingsReceived)
for users participating in auto-matched collaborations. Stats are updated when
both users complete mutual ratings after a recording session.

Changes:
- Add suggestionId, source, and statsApplied fields to Match model
- Implement applyRecordingStatsForMatch() helper with user role convention
  (user1 = dancer, user2 = recorder)
- Update suggestion status endpoint to create Match on acceptance
- Update ratings endpoint to apply stats when match is completed
- Add comprehensive unit tests (5) and integration tests (5)

Convention: Stats only updated for auto-matches (source='auto') to ensure
fairness metrics reflect actual algorithmic assignments, not manual matches.

Test Results: 304/305 tests passing (99.7%)
Coverage: 74.53% (+1.48%)
This commit is contained in:
Radosław Gierwiało
2025-11-30 10:40:43 +01:00
parent 5ee1e0a4b9
commit 145c9f7ce6
6 changed files with 741 additions and 22 deletions

View File

@@ -165,17 +165,24 @@ model Match {
user1LastReadAt DateTime? @map("user1_last_read_at")
user2LastReadAt DateTime? @map("user2_last_read_at")
// Auto-matching integration
suggestionId Int? @unique @map("suggestion_id") // Link to auto-matching suggestion (optional)
source String @default("manual") @db.VarChar(20) // 'manual' | 'auto'
statsApplied Boolean @default(false) @map("stats_applied") // Flag to ensure stats applied only once
// Relations
user1 User @relation("MatchUser1", fields: [user1Id], references: [id])
user2 User @relation("MatchUser2", fields: [user2Id], references: [id])
event Event @relation(fields: [eventId], references: [id])
room ChatRoom? @relation(fields: [roomId], references: [id])
ratings Rating[]
user1 User @relation("MatchUser1", fields: [user1Id], references: [id])
user2 User @relation("MatchUser2", fields: [user2Id], references: [id])
event Event @relation(fields: [eventId], references: [id])
room ChatRoom? @relation(fields: [roomId], references: [id])
suggestion RecordingSuggestion? @relation(fields: [suggestionId], references: [id])
ratings Rating[]
@@unique([user1Id, user2Id, eventId])
@@index([user1Id])
@@index([user2Id])
@@index([eventId])
@@index([suggestionId])
@@map("matches")
}
@@ -285,6 +292,7 @@ model RecordingSuggestion {
event Event @relation(fields: [eventId], references: [id], onDelete: Cascade)
heat EventUserHeat @relation(fields: [heatId], references: [id], onDelete: Cascade)
recorder User? @relation("RecorderAssignments", fields: [recorderId], references: [id])
match Match? // Link to created match (if suggestion was accepted)
@@index([eventId])
@@index([recorderId])