20a1c143f3
Fetching a symbol the provider doesn't cover (e.g. RHM/Rheinmetall — Alpaca serves US listings only) returned 0 bars but reported "complete · Successfully ingested 0 records", which the UI showed as green success. fetch_and_ingest now returns a distinct `no_data` status when the provider returns nothing AND the ticker has no history (vs. "already up to date" when bars exist). The fetch endpoint maps it to a `warning` source status, and the fetch toast renders it as ⚠ with the provider message instead of success. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
import type { FetchDataResult, IngestionSourceResult } from '../api/ingestion';
|
|
|
|
export type IngestionToastType = 'success' | 'error' | 'info';
|
|
|
|
export interface IngestionStatusSummary {
|
|
toastType: IngestionToastType;
|
|
message: string;
|
|
}
|
|
|
|
export function summarizeIngestionResult(
|
|
result: FetchDataResult | null | undefined,
|
|
fallbackLabel: string,
|
|
): IngestionStatusSummary {
|
|
const sources = result?.sources;
|
|
if (!sources) {
|
|
return {
|
|
toastType: 'success',
|
|
message: `Data fetched for ${fallbackLabel}`,
|
|
};
|
|
}
|
|
|
|
const entries = Object.entries(sources) as [string, IngestionSourceResult][];
|
|
const parts = entries.map(([name, info]) => {
|
|
const label = name.charAt(0).toUpperCase() + name.slice(1);
|
|
if (info.status === 'ok') {
|
|
return `${label} ✓`;
|
|
}
|
|
if (info.status === 'warning') {
|
|
return `${label} ⚠${info.message ? `: ${info.message}` : ': no data'}`;
|
|
}
|
|
if (info.status === 'skipped') {
|
|
return `${label}: skipped${info.message ? ` (${info.message})` : ''}`;
|
|
}
|
|
return `${label} ✗${info.message ? `: ${info.message}` : ''}`;
|
|
});
|
|
|
|
const hasError = entries.some(([, source]) => source.status === 'error');
|
|
const hasWarning = entries.some(([, source]) => source.status === 'warning');
|
|
const hasSkip = entries.some(([, source]) => source.status === 'skipped');
|
|
// A warning (e.g. 0 bars returned) must not read as success.
|
|
const toastType: IngestionToastType = hasError ? 'error' : hasWarning || hasSkip ? 'info' : 'success';
|
|
|
|
return {
|
|
toastType,
|
|
message: parts.join(' · '),
|
|
};
|
|
}
|