Fix financial taxonomy snapshot normalization
This commit is contained in:
@@ -45,6 +45,7 @@ import {
|
||||
type NumberScaleUnit
|
||||
} from '@/lib/format';
|
||||
import { buildGraphingHref } from '@/lib/graphing/catalog';
|
||||
import { mergeFinancialPages } from '@/lib/financials/page-merge';
|
||||
import {
|
||||
buildStatementTree,
|
||||
resolveStatementSelection,
|
||||
@@ -63,7 +64,6 @@ import type {
|
||||
RatioRow,
|
||||
StandardizedFinancialRow,
|
||||
StructuredKpiRow,
|
||||
SurfaceDetailMap,
|
||||
SurfaceFinancialRow,
|
||||
TaxonomyStatementRow,
|
||||
TrendSeries
|
||||
@@ -345,90 +345,6 @@ function groupRows(rows: FlatDisplayRow[], categories: CompanyFinancialStatement
|
||||
.filter((group) => group.rows.length > 0);
|
||||
}
|
||||
|
||||
function mergeDetailMaps(base: SurfaceDetailMap | null, next: SurfaceDetailMap | null) {
|
||||
if (!base) {
|
||||
return next;
|
||||
}
|
||||
|
||||
if (!next) {
|
||||
return base;
|
||||
}
|
||||
|
||||
const merged: SurfaceDetailMap = structuredClone(base);
|
||||
|
||||
for (const [surfaceKey, detailRows] of Object.entries(next)) {
|
||||
const existingRows = merged[surfaceKey] ?? [];
|
||||
const rowMap = new Map(existingRows.map((row) => [row.key, row]));
|
||||
|
||||
for (const detailRow of detailRows) {
|
||||
const existing = rowMap.get(detailRow.key);
|
||||
if (!existing) {
|
||||
rowMap.set(detailRow.key, structuredClone(detailRow));
|
||||
continue;
|
||||
}
|
||||
|
||||
existing.values = {
|
||||
...existing.values,
|
||||
...detailRow.values
|
||||
};
|
||||
existing.sourceFactIds = [...new Set([...existing.sourceFactIds, ...detailRow.sourceFactIds])];
|
||||
existing.dimensionsSummary = [...new Set([...existing.dimensionsSummary, ...detailRow.dimensionsSummary])];
|
||||
}
|
||||
|
||||
merged[surfaceKey] = [...rowMap.values()];
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
function mergeFinancialPages(
|
||||
base: CompanyFinancialStatementsResponse | null,
|
||||
next: CompanyFinancialStatementsResponse
|
||||
) {
|
||||
if (!base) {
|
||||
return next;
|
||||
}
|
||||
|
||||
const periods = [...base.periods, ...next.periods]
|
||||
.filter((period, index, list) => list.findIndex((item) => item.id === period.id) === index)
|
||||
.sort((left, right) => Date.parse(left.periodEnd ?? left.filingDate) - Date.parse(right.periodEnd ?? right.filingDate));
|
||||
|
||||
const mergeRows = <T extends { key: string; values: Record<string, number | null> }>(rows: T[]) => {
|
||||
const map = new Map<string, T>();
|
||||
for (const row of rows) {
|
||||
const existing = map.get(row.key);
|
||||
if (!existing) {
|
||||
map.set(row.key, structuredClone(row));
|
||||
continue;
|
||||
}
|
||||
|
||||
existing.values = {
|
||||
...existing.values,
|
||||
...row.values
|
||||
};
|
||||
}
|
||||
|
||||
return [...map.values()];
|
||||
};
|
||||
|
||||
return {
|
||||
...next,
|
||||
periods,
|
||||
statementRows: next.statementRows && base.statementRows
|
||||
? {
|
||||
faithful: mergeRows([...base.statementRows.faithful, ...next.statementRows.faithful]),
|
||||
standardized: mergeRows([...base.statementRows.standardized, ...next.statementRows.standardized])
|
||||
}
|
||||
: next.statementRows,
|
||||
statementDetails: mergeDetailMaps(base.statementDetails, next.statementDetails),
|
||||
ratioRows: next.ratioRows && base.ratioRows ? mergeRows([...base.ratioRows, ...next.ratioRows]) : next.ratioRows,
|
||||
kpiRows: next.kpiRows && base.kpiRows ? mergeRows([...base.kpiRows, ...next.kpiRows]) : next.kpiRows,
|
||||
trendSeries: next.trendSeries,
|
||||
categories: next.categories,
|
||||
dimensionBreakdown: next.dimensionBreakdown ?? base.dimensionBreakdown
|
||||
};
|
||||
}
|
||||
|
||||
function ChartFrame({ children }: { children: React.ReactNode }) {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [ready, setReady] = useState(false);
|
||||
@@ -1185,11 +1101,11 @@ function FinancialsPageContent() {
|
||||
{isDerivedRow(selectedRow) ? (
|
||||
<div className="rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2">
|
||||
<p className="text-[color:var(--terminal-muted)]">Source Row Keys</p>
|
||||
<p className="font-semibold text-[color:var(--terminal-bright)]">{selectedRow.sourceRowKeys.join(', ') || 'n/a'}</p>
|
||||
<p className="font-semibold text-[color:var(--terminal-bright)]">{(selectedRow.sourceRowKeys ?? []).join(', ') || 'n/a'}</p>
|
||||
<p className="mt-2 text-[color:var(--terminal-muted)]">Source Concepts</p>
|
||||
<p className="font-semibold text-[color:var(--terminal-bright)]">{selectedRow.sourceConcepts.join(', ') || 'n/a'}</p>
|
||||
<p className="font-semibold text-[color:var(--terminal-bright)]">{(selectedRow.sourceConcepts ?? []).join(', ') || 'n/a'}</p>
|
||||
<p className="mt-2 text-[color:var(--terminal-muted)]">Source Fact IDs</p>
|
||||
<p className="font-semibold text-[color:var(--terminal-bright)]">{selectedRow.sourceFactIds.join(', ') || 'n/a'}</p>
|
||||
<p className="font-semibold text-[color:var(--terminal-bright)]">{(selectedRow.sourceFactIds ?? []).join(', ') || 'n/a'}</p>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@@ -1271,7 +1187,7 @@ function FinancialsPageContent() {
|
||||
surfaceKind
|
||||
})}</td>
|
||||
<td>{check.status}</td>
|
||||
<td>{check.evidencePages.join(', ') || 'n/a'}</td>
|
||||
<td>{(check.evidencePages ?? []).join(', ') || 'n/a'}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user