2b89fcf483
DashboardReadService no longer loads full entity lists and filters in memory. All job panels (today/overdue/in-progress) now execute targeted COUNT + capped SELECT queries in SQL. AR aging buckets, powder order lines, bill totals, and active-customer counts are all aggregated at the DB level. The SuperAdmin action previously loaded every company row to compute plan distribution and alert lists; it now delegates to a new GetSuperAdminDashboardDataAsync() that uses SQL GROUP BY and projections instead. DashboardIndexData record updated to carry pre-sliced counts and capped lists so the controller only does lightweight DTO projection. DashboardPowderOrderLineData replaces the deep Job→JobItem→Coat Include chains with a single flat coat query projected in SQL. OnlineUserMiddleware switches its per-user throttle from a static ConcurrentDictionary (grows forever) to IMemoryCache with a 60-second sliding expiry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>