Rework insider feed: system-level InsiderWatch + dedicated view (no watchlist writes) Watchlists will become per-user once the product is offered commercially, so the system must not auto-add/remove traders there. Decouple insider tracking entirely: - New system-owned entity InsiderWatch (TraderId unique, FirstDetectedAt, LastAlertedTradeAt) + IInsiderWatchRepository; migration AddInsiderWatch. - AlertService.EvaluateInsiderWatchAsync now maintains InsiderWatch (not the watchlist): registers each possible_insider wallet, seeds the high-water mark at detection time, and fires one InsiderActivity alert per new trade. Dedup via LastAlertedTradeAt. - Dedicated "Insider" view: GET /api/traders/insiders + InsiderDto + a new Insider-Radar page (sorted by market-surprise). Read-only, separate from watchlist. - Revert the WatchlistEntry.LastInsiderAlertAt field + its migration (unapplied); drop the now-unused IWatchlistRepository.UpdateAsync. - Tests updated to assert InsiderWatch registry (and that no WatchlistEntry is created). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> @
30 lines
1.2 KiB
C#
30 lines
1.2 KiB
C#
using Predictalytics.Domain.Entities;
|
|
using Predictalytics.Domain.Interfaces;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Predictalytics.Infrastructure.Data.Repositories;
|
|
|
|
public class WatchlistRepository : IWatchlistRepository
|
|
{
|
|
private readonly AppDbContext _db;
|
|
public WatchlistRepository(AppDbContext db) => _db = db;
|
|
|
|
public async Task<IReadOnlyList<WatchlistEntry>> GetAllAsync(CancellationToken ct = default)
|
|
=> await _db.WatchlistEntries
|
|
.Include(w => w.Trader)
|
|
.ThenInclude(t => t.Analytics)
|
|
.ToListAsync(ct);
|
|
|
|
public async Task<WatchlistEntry?> GetByTraderIdAsync(int traderId, CancellationToken ct = default)
|
|
=> await _db.WatchlistEntries.FirstOrDefaultAsync(w => w.TraderId == traderId, ct);
|
|
|
|
public async Task AddAsync(WatchlistEntry entry, CancellationToken ct = default)
|
|
{ _db.WatchlistEntries.Add(entry); await _db.SaveChangesAsync(ct); }
|
|
|
|
public async Task RemoveAsync(int id, CancellationToken ct = default)
|
|
{
|
|
var e = await _db.WatchlistEntries.FindAsync(new object[] { id }, ct);
|
|
if (e != null) { _db.WatchlistEntries.Remove(e); await _db.SaveChangesAsync(ct); }
|
|
}
|
|
}
|