fix: a review window needs a baseline — say which one, refuse ones that have none
- charter: a window starting before the data or longer than 12 weeks is split (last 6 weeks vs the 8 before); REVIEWED always names the compared periods, never the requested span or the whole table - Run review: shows the data's span, previews the exact recent and baseline periods, blocks a window whose baseline would fall before the first claim, and sends 'data as of' only when no window end is given Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
91002b11c4
commit
77cf90e40b
@ -1,7 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Brain, CalendarRange, Database, Radar } from 'lucide-react';
|
||||
import { useZino } from '../api/provider';
|
||||
import { useQuery, useZino } from '../api/provider';
|
||||
import { addDays } from '../api/charts';
|
||||
import { str } from '../format';
|
||||
import { ACT, LAKEHOUSE, QUIET_MORNING_AS_OF, WORKFLOW } from '../api/config';
|
||||
import { Button, Card, ErrorNote, Input, Label } from '../components/core';
|
||||
import { shortDate } from '../format';
|
||||
@ -28,14 +30,29 @@ export function RunReviewScreen() {
|
||||
const [from, setFrom] = useState('');
|
||||
const [to, setTo] = useState('');
|
||||
|
||||
// The data's own span, so a window cannot be set where there is nothing to
|
||||
// compare: a start before the first claim leaves no baseline, and a run on
|
||||
// such a window would have to improvise one.
|
||||
const stats = useQuery(() => client.rows('dni-rv-lakehouse-tables', { limit: 10 }), []);
|
||||
const claimsStats = stats.data?.find((r) => str(r.table_name) === 'claims');
|
||||
const dataFrom = str(claimsStats?.from_date).slice(0, 10) || null;
|
||||
const dataTo = str(claimsStats?.to_date).slice(0, 10) || null;
|
||||
|
||||
// The window Ava will actually use, so the reviewer sees it before pressing Run.
|
||||
const effectiveTo = to || asOf;
|
||||
const weeks = from && effectiveTo ? Math.round((new Date(effectiveTo).getTime() - new Date(from).getTime()) / 604800000) : null;
|
||||
const split = weeks != null && weeks > 12;
|
||||
const recentFrom = split && effectiveTo ? addDays(effectiveTo, -41) : from || (effectiveTo ? addDays(effectiveTo, -41) : '');
|
||||
const baseFrom = recentFrom ? addDays(recentFrom, -56) : '';
|
||||
const baseTo = recentFrom ? addDays(recentFrom, -1) : '';
|
||||
const dateErr =
|
||||
from && effectiveTo && from > effectiveTo
|
||||
? 'The window must start before it ends.'
|
||||
: to && asOf && to > asOf
|
||||
? '"Window to" cannot be after "data as of".'
|
||||
: null;
|
||||
: dataFrom && baseFrom && baseFrom < dataFrom
|
||||
? `The 8-week baseline before ${shortDate(recentFrom)} needs data from ${shortDate(baseFrom)}, but the data begins ${shortDate(dataFrom)}. Start the window on or after ${shortDate(addDays(dataFrom, 56))}.`
|
||||
: null;
|
||||
|
||||
async function run(custom: boolean) {
|
||||
setBusy(custom ? 'custom' : 'now');
|
||||
@ -45,7 +62,8 @@ export function RunReviewScreen() {
|
||||
// reviewer set, so a plain run is a genuinely empty submission.
|
||||
const data: Record<string, string> = {};
|
||||
if (custom) {
|
||||
if (asOf) data.review_as_of__review = asOf;
|
||||
// "Window to" is the ceiling; "data as of" only matters when no window end is given.
|
||||
if (asOf && !to) data.review_as_of__review = asOf;
|
||||
if (from) data.review_from__review = from;
|
||||
if (to) data.review_to__review = to;
|
||||
}
|
||||
@ -121,6 +139,7 @@ export function RunReviewScreen() {
|
||||
<p className="mt-0.5 text-sm text-muted">
|
||||
Replay a past morning, or point the review at a specific period. Leave a date blank to
|
||||
use the default.
|
||||
{dataFrom && dataTo ? ` Data available ${shortDate(dataFrom)} – ${shortDate(dataTo)}, ${dataTo.slice(0, 4)}.` : ''}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -150,11 +169,12 @@ export function RunReviewScreen() {
|
||||
<>
|
||||
Ava will compare{' '}
|
||||
<span className="font-semibold text-ink">
|
||||
{from ? shortDate(from) : effectiveTo ? '6 weeks before' : 'the last 6 weeks'}
|
||||
{from || effectiveTo ? ` – ${effectiveTo ? shortDate(effectiveTo) : 'latest data'}` : ''}
|
||||
{recentFrom ? `${shortDate(recentFrom)} – ${shortDate(effectiveTo)}` : 'the last 6 weeks'}
|
||||
</span>{' '}
|
||||
against the 8 weeks before it
|
||||
{asOf ? `, treating ${shortDate(asOf)} as the latest date` : ''}.
|
||||
against{' '}
|
||||
<span className="font-semibold text-ink">{baseFrom ? `${shortDate(baseFrom)} – ${shortDate(baseTo)}` : 'the 8 weeks before'}</span>
|
||||
{effectiveTo ? `, ignoring anything after ${shortDate(effectiveTo)}` : ''}.
|
||||
{split ? ` A window longer than 12 weeks has no baseline of its own, so its last 6 weeks are compared with the 8 before them.` : ''}
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user