Browse Source

Bugfix/fix import of empty account balances (#4677)

* Fix import of empty account balances

* Update changelog

---------

Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
pull/4847/head
Alison Hawk 4 weeks ago
committed by GitHub
parent
commit
31f5c0de88
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 2
      apps/api/src/app/import/create-account-with-balances.dto.ts
  3. 2
      apps/api/src/app/import/import.controller.ts
  4. 28
      apps/api/src/app/import/import.service.ts
  5. 10
      test/import/ok.json

1
CHANGELOG.md

@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Fixed an issue where the import button was not correctly enabled in the import activities dialog - Fixed an issue where the import button was not correctly enabled in the import activities dialog
- Fixed an issue with empty account balances in the import activities dialog
- Fixed an issue in the annualized performance calculation - Fixed an issue in the annualized performance calculation
## 2.166.0 - 2025-06-05 ## 2.166.0 - 2025-06-05

2
apps/api/src/app/import/create-account-with-balances.dto.ts

@ -6,5 +6,5 @@ import { IsArray, IsOptional } from 'class-validator';
export class CreateAccountWithBalancesDto extends CreateAccountDto { export class CreateAccountWithBalancesDto extends CreateAccountDto {
@IsArray() @IsArray()
@IsOptional() @IsOptional()
balances?: AccountBalance; balances?: AccountBalance[];
} }

2
apps/api/src/app/import/import.controller.ts

@ -71,7 +71,7 @@ export class ImportController {
const activities = await this.importService.import({ const activities = await this.importService.import({
isDryRun, isDryRun,
maxActivitiesToImport, maxActivitiesToImport,
accountsDto: importData.accounts ?? [], accountsWithBalancesDto: importData.accounts ?? [],
activitiesDto: importData.activities, activitiesDto: importData.activities,
user: this.request.user user: this.request.user
}); });

28
apps/api/src/app/import/import.service.ts

@ -28,9 +28,11 @@ import { Injectable } from '@nestjs/common';
import { DataSource, Prisma, SymbolProfile } from '@prisma/client'; import { DataSource, Prisma, SymbolProfile } from '@prisma/client';
import { Big } from 'big.js'; import { Big } from 'big.js';
import { endOfToday, isAfter, isSameSecond, parseISO } from 'date-fns'; import { endOfToday, isAfter, isSameSecond, parseISO } from 'date-fns';
import { uniqBy } from 'lodash'; import { omit, uniqBy } from 'lodash';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { ImportDataDto } from './import-data.dto';
@Injectable() @Injectable()
export class ImportService { export class ImportService {
public constructor( public constructor(
@ -138,14 +140,14 @@ export class ImportService {
} }
public async import({ public async import({
accountsDto, accountsWithBalancesDto,
activitiesDto, activitiesDto,
isDryRun = false, isDryRun = false,
maxActivitiesToImport, maxActivitiesToImport,
user user
}: { }: {
accountsDto: Partial<CreateAccountDto>[]; accountsWithBalancesDto: ImportDataDto['accounts'];
activitiesDto: Partial<CreateOrderDto>[]; activitiesDto: ImportDataDto['activities'];
isDryRun?: boolean; isDryRun?: boolean;
maxActivitiesToImport: number; maxActivitiesToImport: number;
user: UserWithSettings; user: UserWithSettings;
@ -153,12 +155,12 @@ export class ImportService {
const accountIdMapping: { [oldAccountId: string]: string } = {}; const accountIdMapping: { [oldAccountId: string]: string } = {};
const userCurrency = user.Settings.settings.baseCurrency; const userCurrency = user.Settings.settings.baseCurrency;
if (!isDryRun && accountsDto?.length) { if (!isDryRun && accountsWithBalancesDto?.length) {
const [existingAccounts, existingPlatforms] = await Promise.all([ const [existingAccounts, existingPlatforms] = await Promise.all([
this.accountService.accounts({ this.accountService.accounts({
where: { where: {
id: { id: {
in: accountsDto.map(({ id }) => { in: accountsWithBalancesDto.map(({ id }) => {
return id; return id;
}) })
} }
@ -167,14 +169,19 @@ export class ImportService {
this.platformService.getPlatforms() this.platformService.getPlatforms()
]); ]);
for (const account of accountsDto) { for (const accountWithBalances of accountsWithBalancesDto) {
// Check if there is any existing account with the same ID // Check if there is any existing account with the same ID
const accountWithSameId = existingAccounts.find((existingAccount) => { const accountWithSameId = existingAccounts.find((existingAccount) => {
return existingAccount.id === account.id; return existingAccount.id === accountWithBalances.id;
}); });
// If there is no account or if the account belongs to a different user then create a new account // If there is no account or if the account belongs to a different user then create a new account
if (!accountWithSameId || accountWithSameId.userId !== user.id) { if (!accountWithSameId || accountWithSameId.userId !== user.id) {
const account: CreateAccountDto = omit(
accountWithBalances,
'balances'
);
let oldAccountId: string; let oldAccountId: string;
const platformId = account.platformId; const platformId = account.platformId;
@ -187,6 +194,9 @@ export class ImportService {
let accountObject: Prisma.AccountCreateInput = { let accountObject: Prisma.AccountCreateInput = {
...account, ...account,
balances: {
create: accountWithBalances.balances ?? []
},
User: { connect: { id: user.id } } User: { connect: { id: user.id } }
}; };
@ -251,7 +261,7 @@ export class ImportService {
); );
if (isDryRun) { if (isDryRun) {
accountsDto.forEach(({ id, name }) => { accountsWithBalancesDto.forEach(({ id, name }) => {
accounts.push({ id, name }); accounts.push({ id, name });
}); });
} }

10
test/import/ok.json

@ -6,6 +6,16 @@
"accounts": [ "accounts": [
{ {
"balance": 2000, "balance": 2000,
"balances": [
{
"date": "2024-12-31T00:00:00.000Z",
"value": 2000
},
{
"date": "2023-12-31T00:00:00.000Z",
"value": 1000
}
],
"currency": "USD", "currency": "USD",
"id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", "id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0",
"isExcluded": false, "isExcluded": false,

Loading…
Cancel
Save