Implement fiscal-style research MVP flows
Some checks failed
PR Checks / typecheck-and-build (push) Has been cancelled
Some checks failed
PR Checks / typecheck-and-build (push) Has been cancelled
This commit is contained in:
@@ -178,6 +178,50 @@ function mergeSurfaceRows<T extends { key: string; values: Record<string, number
|
||||
return [...rowMap.values()];
|
||||
}
|
||||
|
||||
function mergeOverviewMetrics(
|
||||
base: CompanyFinancialStatementsResponse['overviewMetrics'],
|
||||
next: CompanyFinancialStatementsResponse['overviewMetrics']
|
||||
): CompanyFinancialStatementsResponse['overviewMetrics'] {
|
||||
const mergedSeriesMap = new Map<string, CompanyFinancialStatementsResponse['overviewMetrics']['series'][number]>();
|
||||
|
||||
for (const source of [base.series, next.series]) {
|
||||
for (const point of source) {
|
||||
const existing = mergedSeriesMap.get(point.periodId);
|
||||
if (!existing) {
|
||||
mergedSeriesMap.set(point.periodId, { ...point });
|
||||
continue;
|
||||
}
|
||||
|
||||
existing.filingDate = existing.filingDate || point.filingDate;
|
||||
existing.periodEnd = existing.periodEnd ?? point.periodEnd;
|
||||
existing.label = existing.label || point.label;
|
||||
existing.revenue = existing.revenue ?? point.revenue;
|
||||
existing.netIncome = existing.netIncome ?? point.netIncome;
|
||||
existing.totalAssets = existing.totalAssets ?? point.totalAssets;
|
||||
existing.cash = existing.cash ?? point.cash;
|
||||
existing.debt = existing.debt ?? point.debt;
|
||||
}
|
||||
}
|
||||
|
||||
const series = [...mergedSeriesMap.values()].sort((left, right) => {
|
||||
return Date.parse(left.periodEnd ?? left.filingDate) - Date.parse(right.periodEnd ?? right.filingDate);
|
||||
});
|
||||
const latest = series[series.length - 1] ?? null;
|
||||
|
||||
return {
|
||||
referencePeriodId: next.referencePeriodId ?? base.referencePeriodId ?? latest?.periodId ?? null,
|
||||
referenceDate: next.referenceDate ?? base.referenceDate ?? latest?.filingDate ?? null,
|
||||
latest: {
|
||||
revenue: next.latest.revenue ?? base.latest.revenue ?? latest?.revenue ?? null,
|
||||
netIncome: next.latest.netIncome ?? base.latest.netIncome ?? latest?.netIncome ?? null,
|
||||
totalAssets: next.latest.totalAssets ?? base.latest.totalAssets ?? latest?.totalAssets ?? null,
|
||||
cash: next.latest.cash ?? base.latest.cash ?? latest?.cash ?? null,
|
||||
debt: next.latest.debt ?? base.latest.debt ?? latest?.debt ?? null
|
||||
},
|
||||
series
|
||||
};
|
||||
}
|
||||
|
||||
function mergeFinancialPages(
|
||||
base: CompanyFinancialStatementsResponse | null,
|
||||
next: CompanyFinancialStatementsResponse
|
||||
@@ -317,6 +361,7 @@ function mergeFinancialPages(
|
||||
...next.dataSourceStatus,
|
||||
queuedSync: base.dataSourceStatus.queuedSync || next.dataSourceStatus.queuedSync
|
||||
},
|
||||
overviewMetrics: mergeOverviewMetrics(base.overviewMetrics, next.overviewMetrics),
|
||||
dimensionBreakdown
|
||||
};
|
||||
}
|
||||
@@ -342,6 +387,33 @@ function buildOverviewSeries(
|
||||
incomeData: CompanyFinancialStatementsResponse | null,
|
||||
balanceData: CompanyFinancialStatementsResponse | null
|
||||
): OverviewPoint[] {
|
||||
const overviewSeriesMap = new Map<string, OverviewPoint>();
|
||||
|
||||
for (const source of [incomeData?.overviewMetrics.series ?? [], balanceData?.overviewMetrics.series ?? []]) {
|
||||
for (const point of source) {
|
||||
const existing = overviewSeriesMap.get(point.periodId);
|
||||
if (!existing) {
|
||||
overviewSeriesMap.set(point.periodId, { ...point });
|
||||
continue;
|
||||
}
|
||||
|
||||
existing.filingDate = existing.filingDate || point.filingDate;
|
||||
existing.periodEnd = existing.periodEnd ?? point.periodEnd;
|
||||
existing.label = existing.label || point.label;
|
||||
existing.revenue = existing.revenue ?? point.revenue;
|
||||
existing.netIncome = existing.netIncome ?? point.netIncome;
|
||||
existing.totalAssets = existing.totalAssets ?? point.totalAssets;
|
||||
existing.cash = existing.cash ?? point.cash;
|
||||
existing.debt = existing.debt ?? point.debt;
|
||||
}
|
||||
}
|
||||
|
||||
if (overviewSeriesMap.size > 0) {
|
||||
return [...overviewSeriesMap.values()].sort((left, right) => {
|
||||
return Date.parse(left.periodEnd ?? left.filingDate) - Date.parse(right.periodEnd ?? right.filingDate);
|
||||
});
|
||||
}
|
||||
|
||||
const periodMap = new Map<string, { filingDate: string; periodEnd: string | null }>();
|
||||
|
||||
for (const source of [incomeData, balanceData]) {
|
||||
@@ -609,27 +681,36 @@ function FinancialsPageContent() {
|
||||
|
||||
const latestStandardizedIncome = overviewIncome?.surfaces.standardized.rows ?? [];
|
||||
const latestStandardizedBalance = overviewBalance?.surfaces.standardized.rows ?? [];
|
||||
const latestRevenue = latestOverview?.revenue
|
||||
const latestRevenue = overviewIncome?.overviewMetrics.latest.revenue
|
||||
?? latestOverview?.revenue
|
||||
?? findStandardizedRow(latestStandardizedIncome, 'revenue')?.values[periods[periods.length - 1]?.id ?? '']
|
||||
?? latestTaxonomyMetrics?.revenue
|
||||
?? null;
|
||||
const latestNetIncome = latestOverview?.netIncome
|
||||
const latestNetIncome = overviewIncome?.overviewMetrics.latest.netIncome
|
||||
?? latestOverview?.netIncome
|
||||
?? findStandardizedRow(latestStandardizedIncome, 'net-income')?.values[periods[periods.length - 1]?.id ?? '']
|
||||
?? latestTaxonomyMetrics?.netIncome
|
||||
?? null;
|
||||
const latestTotalAssets = latestOverview?.totalAssets
|
||||
const latestTotalAssets = overviewBalance?.overviewMetrics.latest.totalAssets
|
||||
?? latestOverview?.totalAssets
|
||||
?? findStandardizedRow(latestStandardizedBalance, 'total-assets')?.values[periods[periods.length - 1]?.id ?? '']
|
||||
?? latestTaxonomyMetrics?.totalAssets
|
||||
?? null;
|
||||
const latestCash = latestOverview?.cash
|
||||
const latestCash = overviewBalance?.overviewMetrics.latest.cash
|
||||
?? latestOverview?.cash
|
||||
?? findStandardizedRow(latestStandardizedBalance, 'cash-and-equivalents')?.values[periods[periods.length - 1]?.id ?? '']
|
||||
?? latestTaxonomyMetrics?.cash
|
||||
?? null;
|
||||
const latestDebt = latestOverview?.debt
|
||||
const latestDebt = overviewBalance?.overviewMetrics.latest.debt
|
||||
?? latestOverview?.debt
|
||||
?? findStandardizedRow(latestStandardizedBalance, 'total-debt')?.values[periods[periods.length - 1]?.id ?? '']
|
||||
?? latestTaxonomyMetrics?.debt
|
||||
?? null;
|
||||
const latestReferenceDate = latestOverview?.filingDate ?? periods[periods.length - 1]?.filingDate ?? null;
|
||||
const latestReferenceDate = overviewIncome?.overviewMetrics.referenceDate
|
||||
?? overviewBalance?.overviewMetrics.referenceDate
|
||||
?? latestOverview?.filingDate
|
||||
?? periods[periods.length - 1]?.filingDate
|
||||
?? null;
|
||||
|
||||
const selectedRow = useMemo(() => {
|
||||
if (!selectedRowKey) {
|
||||
|
||||
Reference in New Issue
Block a user