fix(frontend): complete audit remediation

This commit is contained in:
2026-09-06 19:49:02 +03:00
parent c97f62bd98
commit 9e42148f6a
11 changed files with 508 additions and 72 deletions
@@ -92,10 +92,13 @@ const useAccountIncomePageViewModel = (): AccountIncomePageViewModel => {
return { state: "error", retry: () => analytics.refetch(), period };
return { state: "loading" };
}
const display = toIncomeDisplayModel(analytics.data);
if (!display)
return { state: "error", retry: () => analytics.refetch(), period };
return {
state: "loaded",
analytics: analytics.data,
display: toIncomeDisplayModel(analytics.data),
display,
forecast: toForecast(events),
form,
onSubmit,
@@ -149,14 +152,32 @@ function isDate(value: string): boolean {
);
}
function toIncomeDisplayModel(analytics: IncomeAnalytics): IncomeDisplayModel {
const entriesByInstrument = new Map<string, IncomeAnalytics["entries"]>();
function toIncomeDisplayModel(
analytics: IncomeAnalytics,
): IncomeDisplayModel | null {
const instruments = new Map<
string,
IncomeDisplayModel["instruments"][number]
>();
for (const instrument of analytics.instruments) {
if (
typeof instrument.key !== "string" ||
!instrument.key.trim() ||
instruments.has(instrument.key)
)
return null;
instruments.set(instrument.key, { ...instrument, entries: [] });
}
for (const entry of analytics.entries) {
const key = incomeEntryKey(entry);
entriesByInstrument.set(key, [
...(entriesByInstrument.get(key) ?? []),
entry,
]);
if (typeof entry.instrumentKey !== "string" || !entry.instrumentKey.trim())
return null;
const instrument = instruments.get(entry.instrumentKey);
if (!instrument || entry.payment?.currency !== instrument.total.currency)
return null;
instrument.entries.push(entry);
}
for (const instrument of instruments.values()) {
if (instrument.entries.length !== instrument.receiptCount) return null;
}
return {
@@ -169,24 +190,10 @@ function toIncomeDisplayModel(analytics: IncomeAnalytics): IncomeDisplayModel {
zeroSummary(currency),
})),
})),
instruments: analytics.instruments.map((instrument) => ({
...instrument,
entries: entriesByInstrument.get(instrument.key) ?? [],
})),
instruments: [...instruments.values()],
};
}
function incomeEntryKey(entry: IncomeAnalytics["entries"][number]): string {
const base = entry.instrumentUid
? `uid:${entry.instrumentUid}`
: entry.figi
? `figi:${entry.figi}`
: entry.ticker || entry.instrumentType
? `ticker:${entry.ticker ?? ""}:${entry.instrumentType ?? ""}`
: `operation:${entry.id}`;
return `${base}:${entry.payment?.currency ?? ""}`;
}
function zeroSummary(
currency: string,
): IncomeAnalytics["totalsByCurrency"][number] {