feat(admin): reset a user's recommendations from the users panel
ci / api / api (push) Successful in 40s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 55s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m10s
ci / db / db (push) Successful in 2m35s
ci / ts / ts (packages + web) (push) Successful in 1m23s

- POST /admin/users/{id}/reset-recommendations clears the taste profile
  (onboarding, CF vector, bandit), play stats and wave impressions; likes,
  dislikes and history stay, wave sessions stay so a playing wave keeps going
- moderators may reset plain users, admins anyone including themselves;
  the reset is written to the audit log
- users panel gets the menu action with a confirmation; docs updated

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Opus 5.5 committed 2026-10-21 08:52:31 +03:00
1 parent b27b915b63
commit 978f03b8f8
20 files changed
+551 -274

No files matched your search

+16
View File
@@ -370,6 +370,22 @@ func (s *PgStore) DeleteUser(ctx context.Context, id uuid.UUID) error {
return nil
}
// ResetRecommendations реализует Store. Сессии волны остаются — играющая волна не ломается;
// без показов бандит при ночном пересчёте начинает заново.
func (s *PgStore) ResetRecommendations(ctx context.Context, id uuid.UUID) error {
for _, q := range []string{
`DELETE FROM user_profiles_rec WHERE user_id = $1`,
`DELETE FROM user_track_stats WHERE user_id = $1`,
`DELETE FROM wave_impressions WHERE wave_session_id IN (SELECT id FROM wave_sessions WHERE user_id = $1)`,
`DELETE FROM rec_impression_features WHERE wave_session_id IN (SELECT id FROM wave_sessions WHERE user_id = $1)`,
} {
if _, err := s.q.Exec(ctx, q, id); err != nil {
return fmt.Errorf("auth: reset recommendations: %w", err)
}
}
return nil
}
// ListAudit реализует Store.
func (s *PgStore) ListAudit(ctx context.Context, before uuid.UUID, limit int) ([]AuditRecord, error) {
rows, err := s.q.Query(ctx, `