refactor!: support RUB only (WealthLedger/main#55) (#168)
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 11s
Frontend verify / verify (push) Failing after 9m0s

This commit was merged in pull request #168.
This commit is contained in:
2026-11-11 09:36:29 +03:00
parent e2062ce837
commit 2b94a16ae5
55 changed files with 540 additions and 1153 deletions
+17 -23
View File
@@ -984,25 +984,21 @@ export interface components {
/** @description Percentage including cash, rounded to six decimal places. Null for incomplete, negative or zero-total compositions. */
sharePercent: string | null;
};
PortfolioStructureCurrencyDto: {
currency: string;
totalValue: string;
/** @description Any negative constituent, even if netted positive. */
hasNegativeValues: boolean;
categories: components["schemas"]["PortfolioStructureCategoryDto"][];
};
PortfolioUnvaluedCategoryDto: {
/** @enum {string} */
type: "STOCK" | "BOND" | "OTHER";
count: number;
};
PortfolioStructureDto: {
currencies: components["schemas"]["PortfolioStructureCurrencyDto"][];
/** @description Positions without current value and known valuation currency. Shares are unavailable across all currencies when nonempty. */
/** @description Exact known total as a decimal string. */
totalValue: string;
/** @description Any negative constituent, even if netted positive. */
hasNegativeValues: boolean;
categories: components["schemas"]["PortfolioStructureCategoryDto"][];
/** @description Positions without current value. Shares are unavailable when nonempty. */
unvaluedCategories: components["schemas"]["PortfolioUnvaluedCategoryDto"][];
};
UnrealizedReturnDto: {
currency: string;
/** @example 12.345678901 */
absolute: string;
/** @example 100.00 */
@@ -1012,10 +1008,10 @@ export interface components {
partial: boolean;
};
PortfolioSummaryDto: {
totalsByCurrency: components["schemas"]["MoneyDto"][];
cashBalances: components["schemas"]["MoneyDto"][];
totals: components["schemas"]["MoneyDto"];
cash: components["schemas"]["MoneyDto"];
structure: components["schemas"]["PortfolioStructureDto"];
unrealizedReturnByCurrency: components["schemas"]["UnrealizedReturnDto"][];
unrealizedReturn: components["schemas"]["UnrealizedReturnDto"];
/** @description Number of non-zero stock positions, not the number of units. */
stockPositionCount: number;
/** @description Number of non-zero bond positions, not the number of units. */
@@ -1145,9 +1141,9 @@ export interface components {
/** Format: date-time */
lastSuccessfulAt: string;
isStale: boolean;
totalsByCurrency: components["schemas"]["MoneyDto"][];
totals: components["schemas"]["MoneyDto"];
positions: components["schemas"]["PortfolioPositionDto"][];
cashBalances: components["schemas"]["MoneyDto"][];
cash: components["schemas"]["MoneyDto"];
structure: components["schemas"]["PortfolioStructureDto"];
};
PortfolioResourceDto: {
@@ -1162,7 +1158,7 @@ export interface components {
days: number;
};
/** @enum {string} */
PerformanceUnavailableReason: "ACCOUNT_VALUATION_DATES_DIFFER" | "AMBIGUOUS_RETURN" | "HISTORY_START_UNKNOWN" | "INDEX_HISTORY_UNAVAILABLE" | "NON_RUB_ACTIVITY" | "NO_SOLUTION" | "OPERATIONS_HISTORY_INCOMPLETE" | "PORTFOLIO_VALUATION_INCOMPLETE" | "UNCONFIRMED_TRANSFER" | "UNVALUED_SECURITIES_TRANSFER";
PerformanceUnavailableReason: "ACCOUNT_VALUATION_DATES_DIFFER" | "AMBIGUOUS_RETURN" | "HISTORY_START_UNKNOWN" | "INDEX_HISTORY_UNAVAILABLE" | "NO_SOLUTION" | "OPERATIONS_HISTORY_INCOMPLETE" | "PORTFOLIO_VALUATION_INCOMPLETE" | "UNCONFIRMED_TRANSFER" | "UNVALUED_SECURITIES_TRANSFER";
PerformanceReturnDto: {
/** @description Decimal fraction: 0.151 = 15.1% */
value: string | null;
@@ -1259,8 +1255,7 @@ export interface components {
/** Format: date */
to: string;
};
IncomeCurrencySummaryDto: {
currency: string;
IncomeTotalDto: {
coupon: components["schemas"]["MoneyDto"];
dividend: components["schemas"]["MoneyDto"];
total: components["schemas"]["MoneyDto"];
@@ -1268,7 +1263,7 @@ export interface components {
IncomeSummaryDto: {
accountId: string;
period: components["schemas"]["IncomePeriodDto"];
totalsByCurrency: components["schemas"]["IncomeCurrencySummaryDto"][];
total: components["schemas"]["IncomeTotalDto"];
/** Format: date-time */
calculatedAt: string;
};
@@ -1278,7 +1273,7 @@ export interface components {
};
IncomeBucketDto: {
period: components["schemas"]["IncomePeriodDto"];
totalsByCurrency: components["schemas"]["IncomeCurrencySummaryDto"][];
total: components["schemas"]["IncomeTotalDto"];
};
IncomeInstrumentDto: {
key: string;
@@ -1316,7 +1311,7 @@ export interface components {
IncomeAnalyticsDto: {
accountId: string;
period: components["schemas"]["IncomePeriodDto"];
totalsByCurrency: components["schemas"]["IncomeCurrencySummaryDto"][];
total: components["schemas"]["IncomeTotalDto"];
/** Format: date-time */
calculatedAt: string;
/** @enum {string} */
@@ -1392,7 +1387,7 @@ export interface components {
/** @description Inclusive UTC window the saved forecast was calculated for. Unchanged by the requested from/to filter. */
window: components["schemas"]["UpcomingEventsWindowDto"];
events: components["schemas"]["UpcomingEventDto"][];
incomeTotalsByCurrency: components["schemas"]["MoneyDto"][];
incomeTotal: components["schemas"]["MoneyDto"];
};
UpcomingEventsResourceDto: {
data: components["schemas"]["UpcomingEventsDto"] | null;
@@ -1451,7 +1446,6 @@ export interface components {
query?: string;
sector?: string;
shareType?: string;
currency?: string;
realExchange?: string;
countryOfRisk?: string;
maxLot?: number;
+5 -5
View File
@@ -20,12 +20,12 @@ function usePrivateResource(accountId: string) {
}
const snapshot: Portfolio = {
cashBalances: [],
cash: { currency: "RUB", value: "0" },
isStale: false,
lastSuccessfulAt: "2026-08-14T00:00:00Z",
positions: [],
structure: { currencies: [], unvaluedCategories: [] },
totalsByCurrency: [{ currency: "RUB", value: "123.000000001" }],
structure: { categories: [], hasNegativeValues: false, totalValue: "0", unvaluedCategories: [] },
totals: { currency: "RUB", value: "123.000000001" },
};
function auth() {
@@ -94,8 +94,8 @@ describe("persistent resource query lifecycle", () => {
isReady = true;
const loaded = await result.current.refetch();
expect(loaded.data).toEqual(refreshed);
expect(loaded.data?.data?.totalsByCurrency).toEqual(
snapshot.totalsByCurrency,
expect(loaded.data?.data?.totals).toEqual(
snapshot.totals,
);
});
await waitFor(() => expect(result.current.data).toEqual(snapshot));
+42 -99
View File
@@ -5871,33 +5871,6 @@
"sharePercent"
]
},
"PortfolioStructureCurrencyDto": {
"type": "object",
"properties": {
"currency": {
"type": "string"
},
"totalValue": {
"type": "string"
},
"hasNegativeValues": {
"type": "boolean",
"description": "Any negative constituent, even if netted positive."
},
"categories": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PortfolioStructureCategoryDto"
}
}
},
"required": [
"currency",
"totalValue",
"hasNegativeValues",
"categories"
]
},
"PortfolioUnvaluedCategoryDto": {
"type": "object",
"properties": {
@@ -5922,14 +5895,22 @@
"PortfolioStructureDto": {
"type": "object",
"properties": {
"currencies": {
"totalValue": {
"type": "string",
"description": "Exact known total as a decimal string."
},
"hasNegativeValues": {
"type": "boolean",
"description": "Any negative constituent, even if netted positive."
},
"categories": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PortfolioStructureCurrencyDto"
"$ref": "#/components/schemas/PortfolioStructureCategoryDto"
}
},
"unvaluedCategories": {
"description": "Positions without current value and known valuation currency. Shares are unavailable across all currencies when nonempty.",
"description": "Positions without current value. Shares are unavailable when nonempty.",
"type": "array",
"items": {
"$ref": "#/components/schemas/PortfolioUnvaluedCategoryDto"
@@ -5937,16 +5918,15 @@
}
},
"required": [
"currencies",
"totalValue",
"hasNegativeValues",
"categories",
"unvaluedCategories"
]
},
"UnrealizedReturnDto": {
"type": "object",
"properties": {
"currency": {
"type": "string"
},
"absolute": {
"type": "string",
"example": "12.345678901"
@@ -5965,7 +5945,6 @@
}
},
"required": [
"currency",
"absolute",
"costBasis",
"percent",
@@ -5975,26 +5954,17 @@
"PortfolioSummaryDto": {
"type": "object",
"properties": {
"totalsByCurrency": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MoneyDto"
}
"totals": {
"$ref": "#/components/schemas/MoneyDto"
},
"cashBalances": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MoneyDto"
}
"cash": {
"$ref": "#/components/schemas/MoneyDto"
},
"structure": {
"$ref": "#/components/schemas/PortfolioStructureDto"
},
"unrealizedReturnByCurrency": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UnrealizedReturnDto"
}
"unrealizedReturn": {
"$ref": "#/components/schemas/UnrealizedReturnDto"
},
"stockPositionCount": {
"type": "integer",
@@ -6018,10 +5988,10 @@
}
},
"required": [
"totalsByCurrency",
"cashBalances",
"totals",
"cash",
"structure",
"unrealizedReturnByCurrency",
"unrealizedReturn",
"stockPositionCount",
"bondPositionCount",
"fundPositionCount",
@@ -6537,11 +6507,8 @@
"isStale": {
"type": "boolean"
},
"totalsByCurrency": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MoneyDto"
}
"totals": {
"$ref": "#/components/schemas/MoneyDto"
},
"positions": {
"type": "array",
@@ -6549,11 +6516,8 @@
"$ref": "#/components/schemas/PortfolioPositionDto"
}
},
"cashBalances": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MoneyDto"
}
"cash": {
"$ref": "#/components/schemas/MoneyDto"
},
"structure": {
"$ref": "#/components/schemas/PortfolioStructureDto"
@@ -6562,9 +6526,9 @@
"required": [
"lastSuccessfulAt",
"isStale",
"totalsByCurrency",
"totals",
"positions",
"cashBalances",
"cash",
"structure"
]
},
@@ -6617,7 +6581,6 @@
"AMBIGUOUS_RETURN",
"HISTORY_START_UNKNOWN",
"INDEX_HISTORY_UNAVAILABLE",
"NON_RUB_ACTIVITY",
"NO_SOLUTION",
"OPERATIONS_HISTORY_INCOMPLETE",
"PORTFOLIO_VALUATION_INCOMPLETE",
@@ -7060,12 +7023,9 @@
"to"
]
},
"IncomeCurrencySummaryDto": {
"IncomeTotalDto": {
"type": "object",
"properties": {
"currency": {
"type": "string"
},
"coupon": {
"$ref": "#/components/schemas/MoneyDto"
},
@@ -7077,7 +7037,6 @@
}
},
"required": [
"currency",
"coupon",
"dividend",
"total"
@@ -7092,11 +7051,8 @@
"period": {
"$ref": "#/components/schemas/IncomePeriodDto"
},
"totalsByCurrency": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IncomeCurrencySummaryDto"
}
"total": {
"$ref": "#/components/schemas/IncomeTotalDto"
},
"calculatedAt": {
"type": "string",
@@ -7106,7 +7062,7 @@
"required": [
"accountId",
"period",
"totalsByCurrency",
"total",
"calculatedAt"
]
},
@@ -7137,16 +7093,13 @@
"period": {
"$ref": "#/components/schemas/IncomePeriodDto"
},
"totalsByCurrency": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IncomeCurrencySummaryDto"
}
"total": {
"$ref": "#/components/schemas/IncomeTotalDto"
}
},
"required": [
"period",
"totalsByCurrency"
"total"
]
},
"IncomeInstrumentDto": {
@@ -7322,11 +7275,8 @@
"period": {
"$ref": "#/components/schemas/IncomePeriodDto"
},
"totalsByCurrency": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IncomeCurrencySummaryDto"
}
"total": {
"$ref": "#/components/schemas/IncomeTotalDto"
},
"calculatedAt": {
"type": "string",
@@ -7362,7 +7312,7 @@
"required": [
"accountId",
"period",
"totalsByCurrency",
"total",
"calculatedAt",
"bucketGranularity",
"buckets",
@@ -7634,11 +7584,8 @@
"$ref": "#/components/schemas/UpcomingEventDto"
}
},
"incomeTotalsByCurrency": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MoneyDto"
}
"incomeTotal": {
"$ref": "#/components/schemas/MoneyDto"
}
},
"required": [
@@ -7646,7 +7593,7 @@
"calculatedAt",
"window",
"events",
"incomeTotalsByCurrency"
"incomeTotal"
]
},
"UpcomingEventsResourceDto": {
@@ -7895,10 +7842,6 @@
"type": "string",
"minLength": 1
},
"currency": {
"type": "string",
"minLength": 1
},
"realExchange": {
"type": "string",
"minLength": 1