fix: stable claims paging and a deep link that does not lose its date window

- claims paging ordered by claim_id (unique) instead of service_date: each page
  is a separate Spark query, and with thousands of ties the engine repeated rows
  across pages
- the case's anchor date comes from the review's own ceiling or the lakehouse
  stats view, not from the briefing, which loads seconds later; an
  expiring-appeals link with no anchor is now suppressed rather than opening
  every unfiled denial

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yashas 2026-09-16 19:11:02 +05:30
parent 1c81912b17
commit 75483f347e
3 changed files with 20 additions and 5 deletions

View File

@ -27,7 +27,10 @@ export function claimsHref(q: ClaimsQuery): string {
/** The rows behind "claims denied" / "affected". */
export function affectedClaimsHref(kind: string, slice: Slice | null, anchor: string | null): string | null {
if (kind === 'expiring_appeals') {
return claimsHref({ status: 'denied', appeal: 'not_filed', dl_from: anchor ?? undefined, dl_to: anchor ? addDays(anchor, 14) : undefined });
// Without the anchor the 14-day window cannot be expressed, and the link
// would open every unfiled denial ever. Show no link instead.
if (!anchor) return null;
return claimsHref({ status: 'denied', appeal: 'not_filed', dl_from: anchor, dl_to: addDays(anchor, 14) });
}
if (kind === 'slow_payer') {
return slice?.payer ? claimsHref({ payer: slice.payer, status: 'pending' }) : null;

View File

@ -17,7 +17,7 @@ import { ActivityForm } from '../components/ActivityForm';
import { AvaLive } from '../components/AvaLive';
import { Disclosure, FullStory, Recheck, Recommendations, SqlEvidence, Verdict } from '../components/Findings';
import { Briefing, BriefingSkeleton } from '../components/Briefing';
import { anchorDate, loadBriefing, sliceOf } from '../api/charts';
import { loadBriefing, sliceOf } from '../api/charts';
import type { Action } from '../api/config';
import { dateTime, num, str } from '../format';
@ -67,7 +67,14 @@ export function CaseScreen() {
// Chart rows come from six Databricks views through the record-view API. Loaded
// once there are findings to picture; the slice keys decide which weekly line
// and which recovery breakdown are drawn.
const asOf = str(row?.review_as_of).slice(0, 10) || null;
const asOf = str(row?.review_to || row?.review_as_of).slice(0, 10) || null;
// The anchor behind "expiring within 14 days". It is the review's own
// ceiling date when the reviewer set one, otherwise the lakehouse's latest
// service date — read from the stats view, NOT from the briefing: the charts
// take seconds to load and a link rendered without the anchor would silently
// drop the deadline window and open thousands of rows instead of hundreds.
const lake = useQuery(() => client.rows('dni-rv-lakehouse-tables', { limit: 10 }), [], !asOf && hasFindings);
const anchor = asOf ?? str(lake.data?.find((r) => str(r.table_name) === 'claims')?.to_date).slice(0, 10) ?? null;
const briefing = useQuery(
() => loadBriefing(client, slice, { kind, asOf }),
[id, slice?.payer, slice?.department, slice?.code, kind, asOf],
@ -171,7 +178,7 @@ export function CaseScreen() {
{/* ---------- The findings: what happened, how much, what to approve ---------- */}
{hasFindings && (
<>
<Verdict row={row} slice={slice} kind={kind} anchor={anchorDate(briefing.data)} />
<Verdict row={row} slice={slice} kind={kind} anchor={anchor || null} />
{briefing.data ? (
<Briefing data={briefing.data} slice={slice} kind={kind} />
) : (

View File

@ -69,8 +69,13 @@ export function ClaimsScreen() {
const filtered = filters.length > 0 || !!search;
const key = params.toString();
// ORDER BY A UNIQUE COLUMN. Each page is its own query against Spark, and
// `service_date` has thousands of ties — with a non-unique sort key the
// engine is free to order tied rows differently per execution, so page 2
// repeated rows from page 1. `claim_id` is unique and is assigned in date
// order, so descending is still newest-first, and every page is disjoint.
const q = useQuery(
() => client.recordView('dni-rv-claims', { page, limit: PAGE, filters, search, sortBy: 'service_date', sortDir: 'desc' }),
() => client.recordView('dni-rv-claims', { page, limit: PAGE, filters, search, sortBy: 'claim_id', sortDir: 'desc' }),
[key],
);
// The platform caps its count at 10,000; the stats view has the exact