Browse Source

Task/remove redundant balance attribute from account (#7546)

* Remove redundant balance attribute from account

* Update changelog
pull/7522/head
Thomas Kaul 1 day ago
committed by GitHub
parent
commit
ddd20d3099
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 48
      apps/api/src/app/account/account.controller.ts
  3. 64
      apps/api/src/app/account/account.service.ts
  4. 4
      apps/api/src/app/account/interfaces/cash-details.interface.ts
  5. 4
      apps/api/src/app/export/export.service.ts
  6. 12
      apps/api/src/app/import/import.service.ts
  7. 7
      apps/api/src/app/portfolio/portfolio.service.spec.ts
  8. 4
      apps/api/src/app/portfolio/portfolio.service.ts
  9. 5
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
  10. 9
      apps/client/src/app/pages/accounts/accounts-page.component.ts
  11. 8
      apps/client/src/app/pages/accounts/create-or-update-account-dialog/interfaces/interfaces.ts
  12. 2
      libs/common/src/lib/config.ts
  13. 7
      libs/common/src/lib/dtos/create-account.dto.ts
  14. 7
      libs/common/src/lib/dtos/update-account.dto.ts
  15. 5
      libs/common/src/lib/types/account-with-balance.type.ts
  16. 6
      libs/common/src/lib/types/account-with-value.type.ts
  17. 2
      libs/common/src/lib/types/index.ts
  18. 20
      libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts
  19. 14
      libs/ui/src/lib/accounts-table/accounts-table.component.ts
  20. 5
      libs/ui/src/lib/activities-table/activities-table.component.stories.ts
  21. 2
      prisma/migrations/20260805120000_removed_balance_from_account/migration.sql
  22. 1
      prisma/schema.prisma
  23. 1
      test/import/not-ok/invalid-platform.json
  24. 1
      test/import/ok/500-activities.json
  25. 1
      test/import/ok/derived-currency.json
  26. 1
      test/import/ok/sample.json

1
CHANGELOG.md

@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the usability of the create watchlist item dialog by setting the initial focus to the search field
- Migrated the abstract _Material_ form field from a component to a directive
- Removed the redundant `balance` attribute of the account in favor of the account balances
## 3.43.0 - 2026-08-06

48
apps/api/src/app/account/account.controller.ts

@ -156,32 +156,34 @@ export class AccountController {
public async createAccount(
@Body() data: CreateAccountDto
): Promise<AccountModel> {
const { tags: tagIds, ...accountData } = data;
const { balance, tags: tagIds, ...accountData } = data;
if (accountData.platformId) {
const platformId = accountData.platformId;
delete accountData.platformId;
return this.accountService.createAccount(
{
return this.accountService.createAccount({
balance,
tagIds,
data: {
...accountData,
platform: { connect: { id: platformId } },
user: { connect: { id: this.request.user.id } }
},
this.request.user.id,
tagIds
);
userId: this.request.user.id
});
} else {
delete accountData.platformId;
return this.accountService.createAccount(
{
return this.accountService.createAccount({
balance,
tagIds,
data: {
...accountData,
user: { connect: { id: this.request.user.id } }
},
this.request.user.id,
tagIds
);
userId: this.request.user.id
});
}
}
@ -257,35 +259,35 @@ export class AccountController {
);
}
const { tags: tagIds, ...accountData } = data;
const { balance, tags: tagIds, ...accountData } = data;
if (accountData.platformId) {
const platformId = accountData.platformId;
delete accountData.platformId;
return this.accountService.updateAccount(
{
return this.accountService.updateAccount({
balance,
tagIds,
data: {
...accountData,
platform: { connect: { id: platformId } },
user: { connect: { id: this.request.user.id } }
},
userId: this.request.user.id,
where: {
id_userId: {
id,
userId: this.request.user.id
}
}
},
this.request.user.id,
tagIds
);
});
} else {
// platformId is null, remove it
delete accountData.platformId;
return this.accountService.updateAccount(
{
return this.accountService.updateAccount({
balance,
tagIds,
data: {
...accountData,
platform: originalAccount.platformId
@ -293,16 +295,14 @@ export class AccountController {
: undefined,
user: { connect: { id: this.request.user.id } }
},
userId: this.request.user.id,
where: {
id_userId: {
id,
userId: this.request.user.id
}
}
},
this.request.user.id,
tagIds
);
});
}
}
}

64
apps/api/src/app/account/account.service.ts

@ -10,6 +10,7 @@ import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { TagService } from '@ghostfolio/api/services/tag/tag.service';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { Filter } from '@ghostfolio/common/interfaces';
import { AccountWithBalance } from '@ghostfolio/common/types';
import { Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
@ -24,7 +25,7 @@ import {
} from '@prisma/client';
import { Big } from 'big.js';
import { endOfToday, format } from 'date-fns';
import { groupBy } from 'lodash';
import { groupBy, isNil } from 'lodash';
import { CashDetails } from './interfaces/cash-details.interface';
@ -40,7 +41,7 @@ export class AccountService {
public async account({
id_userId
}: Prisma.AccountWhereUniqueInput): Promise<Account | null> {
}: Prisma.AccountWhereUniqueInput): Promise<AccountWithBalance | null> {
const account = await this.prismaService.account.findUnique({
include: {
balances: {
@ -87,7 +88,7 @@ export class AccountService {
where?: Prisma.AccountWhereInput;
orderBy?: Prisma.AccountOrderByWithRelationInput;
}): Promise<
(Account & {
(AccountWithBalance & {
activities?: (Order & { SymbolProfile?: SymbolProfile })[];
balances?: AccountBalance[];
platform?: Platform;
@ -160,12 +161,18 @@ export class AccountService {
});
}
public async createAccount(
data: Prisma.AccountCreateInput,
aUserId: string,
tagIds?: string[]
): Promise<Account> {
await this.tagService.validateTagIds({ tagIds, userId: aUserId });
public async createAccount({
balance,
data,
tagIds,
userId
}: {
balance?: number;
data: Prisma.AccountCreateInput;
tagIds?: string[];
userId: string;
}): Promise<Account> {
await this.tagService.validateTagIds({ tagIds, userId });
const account = await this.prismaService.account.create({
data: {
@ -182,12 +189,14 @@ export class AccountService {
}
});
if (!isNil(balance)) {
await this.accountBalanceService.createOrUpdateAccountBalance({
balance,
userId,
accountId: account.id,
balance: data.balance,
date: format(new Date(), DATE_FORMAT),
userId: aUserId
date: format(new Date(), DATE_FORMAT)
});
}
this.eventEmitter.emit(
PortfolioChangedEvent.getName(),
@ -216,7 +225,7 @@ export class AccountService {
return account;
}
public async getAccounts(aUserId: string): Promise<Account[]> {
public async getAccounts(aUserId: string): Promise<AccountWithBalance[]> {
const accounts = await this.accounts({
include: {
activities: true,
@ -295,17 +304,20 @@ export class AccountService {
};
}
public async updateAccount(
params: {
public async updateAccount({
balance,
data,
tagIds,
userId,
where
}: {
balance?: number;
data: Prisma.AccountUpdateInput;
tagIds?: string[];
userId: string;
where: Prisma.AccountWhereUniqueInput;
},
aUserId: string,
tagIds?: string[]
): Promise<Account> {
const { data, where } = params;
await this.tagService.validateTagIds({ tagIds, userId: aUserId });
}): Promise<Account> {
await this.tagService.validateTagIds({ tagIds, userId });
const account = await this.prismaService.account.update({
data: {
@ -324,12 +336,14 @@ export class AccountService {
where
});
if (!isNil(balance)) {
await this.accountBalanceService.createOrUpdateAccountBalance({
balance,
userId,
accountId: account.id,
balance: data.balance as number,
date: format(new Date(), DATE_FORMAT),
userId: aUserId
date: format(new Date(), DATE_FORMAT)
});
}
this.eventEmitter.emit(
PortfolioChangedEvent.getName(),

4
apps/api/src/app/account/interfaces/cash-details.interface.ts

@ -1,6 +1,6 @@
import { Account } from '@prisma/client';
import { AccountWithBalance } from '@ghostfolio/common/types';
export interface CashDetails {
accounts: Account[];
accounts: AccountWithBalance[];
balanceInBaseCurrency: number;
}

4
apps/api/src/app/export/export.service.ts

@ -102,7 +102,6 @@ export class ExportService {
})
.map(
({
balance,
balances,
comment,
currency,
@ -111,13 +110,12 @@ export class ExportService {
platform,
platformId,
tags
}) => {
}): ExportResponse['accounts'][number] => {
if (platformId) {
platformsMap[platformId] = platform;
}
return {
balance,
balances: balances.map(({ date, value }) => {
return { date: date.toISOString(), value };
}),

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

@ -355,6 +355,7 @@ export class ImportService {
// 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) {
const account = omit(accountWithBalances, [
'balance',
'balances',
'isExcluded',
'tags'
@ -408,11 +409,12 @@ export class ImportService {
};
}
const newAccount = await this.accountService.createAccount(
accountObject,
user.id,
tagIds
);
const newAccount = await this.accountService.createAccount({
tagIds,
balance: accountWithBalances.balance,
data: accountObject,
userId: user.id
});
// Store the new to old account ID mappings for updating activities
if (accountWithSameId && oldAccountId) {

7
apps/api/src/app/portfolio/portfolio.service.spec.ts

@ -16,8 +16,9 @@ import {
AssetProfileIdentifier,
PortfolioSummary
} from '@ghostfolio/common/interfaces';
import { AccountWithBalance } from '@ghostfolio/common/types';
import { Account, DataSource } from '@prisma/client';
import { DataSource } from '@prisma/client';
import { Big } from 'big.js';
import { randomUUID } from 'node:crypto';
@ -219,7 +220,7 @@ describe('PortfolioService', () => {
it('should return cash holdings when the calculator emits cash positions with the exchange-rate data source', async () => {
const accountId = randomUUID();
const cashAccount: Account = {
const cashAccount: AccountWithBalance = {
balance: 2000,
comment: null,
createdAt: parseDate('2024-01-01'),
@ -444,7 +445,7 @@ describe('PortfolioService', () => {
beforeEach(() => {
jest
.spyOn(accountService, 'getAccounts')
.mockResolvedValue([account] as unknown as Account[]);
.mockResolvedValue([account] as unknown as AccountWithBalance[]);
jest
.spyOn(exchangeRateDataService, 'toCurrency')

4
apps/api/src/app/portfolio/portfolio.service.ts

@ -64,6 +64,7 @@ import {
} from '@ghostfolio/common/interfaces';
import { TimelinePosition } from '@ghostfolio/common/models';
import {
AccountWithBalance,
AccountWithValue,
DateRange,
GroupBy,
@ -75,7 +76,6 @@ import { PerformanceCalculationType } from '@ghostfolio/common/types/performance
import { Inject, Injectable, Logger } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import {
Account,
Type as ActivityType,
AssetClass,
AssetSubClass,
@ -2142,7 +2142,7 @@ export class PortfolioService {
const accounts: PortfolioDetails['accounts'] = {};
const platforms: PortfolioDetails['platforms'] = {};
let currentAccounts: (Account & {
let currentAccounts: (AccountWithBalance & {
Order?: Order[];
platform?: Platform;
tags?: Tag[];

5
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts

@ -22,6 +22,7 @@ import {
} from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { internalRoutes } from '@ghostfolio/common/routes/routes';
import { AccountWithValue } from '@ghostfolio/common/types';
import { GfAccountsTableComponent } from '@ghostfolio/ui/accounts-table';
import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table';
import { GfDataProviderCreditsComponent } from '@ghostfolio/ui/data-provider-credits';
@ -65,7 +66,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { NavigationStart, Router, RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone';
import { Account, MarketData, Tag } from '@prisma/client';
import { MarketData, Tag } from '@prisma/client';
import { isUUID } from 'class-validator';
import { format, isSameMonth, isToday, parseISO } from 'date-fns';
import { addIcons } from 'ionicons';
@ -117,7 +118,7 @@ import {
templateUrl: 'holding-detail-dialog.html'
})
export class GfHoldingDetailDialogComponent implements OnInit {
protected accounts: Account[];
protected accounts: AccountWithValue[];
protected activitiesCount: number;
protected assetClass: string;
protected assetProfile: Pick<

9
apps/client/src/app/pages/accounts/accounts-page.component.ts

@ -12,6 +12,7 @@ import {
} from '@ghostfolio/common/dtos';
import { User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { AccountWithValue } from '@ghostfolio/common/types';
import { GfAccountsTableComponent } from '@ghostfolio/ui/accounts-table';
import { GfFabComponent } from '@ghostfolio/ui/fab';
import { NotificationService } from '@ghostfolio/ui/notifications';
@ -29,7 +30,7 @@ import {
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { Account as AccountModel, Tag } from '@prisma/client';
import { Tag } from '@prisma/client';
import { DeviceDetectorService } from 'ngx-device-detector';
import { EMPTY } from 'rxjs';
import { catchError } from 'rxjs/operators';
@ -48,7 +49,7 @@ import { GfTransferBalanceDialogComponent } from './transfer-balance/transfer-ba
templateUrl: './accounts-page.html'
})
export class GfAccountsPageComponent implements OnInit {
protected accounts: AccountModel[];
protected accounts: AccountWithValue[];
protected activitiesCount = 0;
protected hasImpersonationId: boolean;
protected hasPermissionToCreateAccount: boolean;
@ -155,7 +156,7 @@ export class GfAccountsPageComponent implements OnInit {
});
}
protected onUpdateAccount(aAccount: AccountModel) {
protected onUpdateAccount(aAccount: AccountWithValue) {
this.router.navigate([], {
queryParams: { accountId: aAccount.id, editDialog: true }
});
@ -194,7 +195,7 @@ export class GfAccountsPageComponent implements OnInit {
name,
platformId,
tags
}: AccountModel & { tags?: Tag[] }) {
}: AccountWithValue & { tags?: Tag[] }) {
const dialogRef = this.dialog.open<
GfCreateOrUpdateAccountDialogComponent,
CreateOrUpdateAccountDialogParams

8
apps/client/src/app/pages/accounts/create-or-update-account-dialog/interfaces/interfaces.ts

@ -1,9 +1,13 @@
import { User } from '@ghostfolio/common/interfaces';
import { AccountWithBalance } from '@ghostfolio/common/types';
import { Account, Tag } from '@prisma/client';
import { Tag } from '@prisma/client';
export interface CreateOrUpdateAccountDialogParams {
account: Omit<Account, 'createdAt' | 'id' | 'updatedAt' | 'userId'> & {
account: Omit<
AccountWithBalance,
'createdAt' | 'id' | 'updatedAt' | 'userId'
> & {
id: string | null;
tags?: Tag[];
};

2
libs/common/src/lib/config.ts

@ -115,7 +115,6 @@ export const DEFAULT_REDACTED_PATHS = [
'accounts[*].interestInBaseCurrency',
'accounts[*].value',
'accounts[*].valueInBaseCurrency',
'activities[*].account.balance',
'activities[*].account.comment',
'activities[*].assetProfile.symbolMapping',
'activities[*].assetProfile.watchedByCount',
@ -128,7 +127,6 @@ export const DEFAULT_REDACTED_PATHS = [
'activities[*].valueInBaseCurrency',
'balance',
'balanceInBaseCurrency',
'balances[*].account.balance',
'balances[*].account.comment',
'balances[*].value',
'balances[*].valueInBaseCurrency',

7
libs/common/src/lib/dtos/create-account.dto.ts

@ -12,8 +12,13 @@ import {
import { isString } from 'lodash';
export class CreateAccountDto {
/**
* The initial balance, stored as the account balance of today.
* Optional because callers may instead supply the full history via `balances`.
*/
@IsNumber()
balance: number;
@IsOptional()
balance?: number;
@IsOptional()
@IsString()

7
libs/common/src/lib/dtos/update-account.dto.ts

@ -12,8 +12,13 @@ import {
import { isString } from 'lodash';
export class UpdateAccountDto {
/**
* The balance, stored as the account balance of today.
* Optional because the account balances are the source of truth.
*/
@IsNumber()
balance: number;
@IsOptional()
balance?: number;
@IsOptional()
@IsString()

5
libs/common/src/lib/types/account-with-balance.type.ts

@ -0,0 +1,5 @@
import { Account as AccountModel } from '@prisma/client';
export type AccountWithBalance = AccountModel & {
balance: number;
};

6
libs/common/src/lib/types/account-with-value.type.ts

@ -1,6 +1,8 @@
import { Account as AccountModel, Platform, Tag } from '@prisma/client';
import { Platform, Tag } from '@prisma/client';
export type AccountWithValue = AccountModel & {
import { AccountWithBalance } from './account-with-balance.type';
export type AccountWithValue = AccountWithBalance & {
activitiesCount: number;
allocationInPercentage: number;
balanceInBaseCurrency: number;

2
libs/common/src/lib/types/index.ts

@ -1,5 +1,6 @@
import type { AccessType } from './access-type.type';
import type { AccessWithGranteeUser } from './access-with-grantee-user.type';
import type { AccountWithBalance } from './account-with-balance.type';
import type { AccountWithPlatform } from './account-with-platform.type';
import type { AccountWithValue } from './account-with-value.type';
import type { AiPromptMode } from './ai-prompt-mode.type';
@ -28,6 +29,7 @@ import type { ViewMode } from './view-mode.type';
export type {
AccessType,
AccessWithGranteeUser,
AccountWithBalance,
AccountWithPlatform,
AccountWithValue,
AiPromptMode,

20
libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts

@ -1,3 +1,5 @@
import { AccountWithValue } from '@ghostfolio/common/types';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
@ -14,16 +16,18 @@ import { NotificationService } from '../notifications';
import { GfValueComponent } from '../value';
import { GfAccountsTableComponent } from './accounts-table.component';
const accounts = [
const accounts: AccountWithValue[] = [
{
activitiesCount: 0,
allocationInPercentage: null,
allocationInPercentage: 0.002574748676949956,
balance: 278,
balanceInBaseCurrency: 278,
comment: null,
createdAt: new Date('2025-06-01T06:52:49.063Z'),
currency: 'USD',
dividendInBaseCurrency: 0,
id: '460d7401-ca43-4ed4-b08e-349f1822e9db',
interestInBaseCurrency: 0,
name: 'Coinbase Account',
platform: {
id: '8dc24b88-bb92-4152-af25-fe6a31643e26',
@ -38,13 +42,15 @@ const accounts = [
},
{
activitiesCount: 0,
allocationInPercentage: null,
allocationInPercentage: 0.11114023065971035,
balance: 12000,
balanceInBaseCurrency: 12000,
comment: null,
createdAt: new Date('2025-06-01T06:48:53.055Z'),
currency: 'USD',
dividendInBaseCurrency: 0,
id: '6d773e31-0583-4c85-a247-e69870b4f1ee',
interestInBaseCurrency: 0,
name: 'Private Banking Account',
platform: {
id: '43e8fcd1-5b79-4100-b678-d2229bd1660d',
@ -59,13 +65,15 @@ const accounts = [
},
{
activitiesCount: 12,
allocationInPercentage: null,
allocationInPercentage: 0.8862850206633397,
balance: 150.2,
balanceInBaseCurrency: 150.2,
comment: null,
createdAt: new Date('2025-05-31T13:00:13.940Z'),
currency: 'USD',
dividendInBaseCurrency: 0,
id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625',
interestInBaseCurrency: 0,
name: 'Trading Account',
platform: {
id: '9da3a8a7-4795-43e3-a6db-ccb914189737',
@ -73,10 +81,10 @@ const accounts = [
url: 'https://interactivebrokers.com'
},
platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737',
valueInBaseCurrency: 95693.70321466809,
updatedAt: new Date('2025-06-01T06:53:10.569Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
value: 95693.70321466809
value: 95693.70321466809,
valueInBaseCurrency: 95693.70321466809
}
];

14
libs/ui/src/lib/accounts-table/accounts-table.component.ts

@ -4,6 +4,7 @@ import {
getLowercase,
isAccountExcluded
} from '@ghostfolio/common/helper';
import { AccountWithValue } from '@ghostfolio/common/types';
import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo';
import { NotificationService } from '@ghostfolio/ui/notifications';
import { GfValueComponent } from '@ghostfolio/ui/value';
@ -24,7 +25,6 @@ import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { Router, RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone';
import { Account } from '@prisma/client';
import { addIcons } from 'ionicons';
import {
arrowRedoOutline,
@ -55,7 +55,7 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
templateUrl: './accounts-table.component.html'
})
export class GfAccountsTableComponent {
public readonly accounts = input.required<Account[]>();
public readonly accounts = input.required<AccountWithValue[]>();
public readonly activitiesCount = input<number>();
public readonly baseCurrency = input<string>();
public readonly hasPermissionToOpenDetails = input(true);
@ -71,12 +71,12 @@ export class GfAccountsTableComponent {
public readonly totalValueInBaseCurrency = input<number>();
public readonly accountDeleted = output<string>();
public readonly accountToUpdate = output<Account>();
public readonly accountToUpdate = output<AccountWithValue>();
public readonly transferBalance = output<void>();
public readonly sort = viewChild.required(MatSort);
protected readonly dataSource = new MatTableDataSource<Account>([]);
protected readonly dataSource = new MatTableDataSource<AccountWithValue>([]);
protected readonly displayedColumns = computed(() => {
const columns = ['status', 'account', 'platform'];
@ -141,7 +141,9 @@ export class GfAccountsTableComponent {
});
}
protected isExcluded(account: Account & { tags?: { id: string }[] }) {
protected isExcluded(
account: AccountWithValue & { tags?: { id: string }[] }
) {
return isAccountExcluded(account);
}
@ -173,7 +175,7 @@ export class GfAccountsTableComponent {
this.transferBalance.emit();
}
protected onUpdateAccount(aAccount: Account) {
protected onUpdateAccount(aAccount: AccountWithValue) {
this.accountToUpdate.emit(aAccount);
}
}

5
libs/ui/src/lib/activities-table/activities-table.component.stories.ts

@ -39,7 +39,6 @@ const activities: Activity[] = [
updatedAt: new Date('2025-05-31T18:43:01.840Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
account: {
balance: 150.2,
comment: null,
createdAt: new Date('2025-05-31T13:00:13.940Z'),
currency: 'USD',
@ -105,7 +104,6 @@ const activities: Activity[] = [
updatedAt: new Date('2025-05-31T18:46:14.175Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
account: {
balance: 150.2,
comment: null,
createdAt: new Date('2025-05-31T13:00:13.940Z'),
currency: 'USD',
@ -171,7 +169,6 @@ const activities: Activity[] = [
updatedAt: new Date('2025-05-31T18:49:54.064Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
account: {
balance: 150.2,
comment: null,
createdAt: new Date('2025-05-31T13:00:13.940Z'),
currency: 'USD',
@ -237,7 +234,6 @@ const activities: Activity[] = [
updatedAt: new Date('2025-05-31T18:48:48.209Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
account: {
balance: 150.2,
comment: null,
createdAt: new Date('2025-05-31T13:00:13.940Z'),
currency: 'USD',
@ -303,7 +299,6 @@ const activities: Activity[] = [
updatedAt: new Date('2025-05-31T18:46:44.616Z'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e',
account: {
balance: 150.2,
comment: null,
createdAt: new Date('2025-05-31T13:00:13.940Z'),
currency: 'USD',

2
prisma/migrations/20260805120000_removed_balance_from_account/migration.sql

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Account" DROP COLUMN "balance";

1
prisma/schema.prisma

@ -27,7 +27,6 @@ model Access {
model Account {
activities Order[]
balance Float @default(0)
balances AccountBalance[]
comment String?
createdAt DateTime @default(now())

1
test/import/not-ok/invalid-platform.json

@ -5,7 +5,6 @@
},
"accounts": [
{
"balance": 0,
"balances": [],
"currency": "USD",
"id": "e62be662-a2c8-4cff-8b79-dc0a46576659",

1
test/import/ok/500-activities.json

@ -5,7 +5,6 @@
},
"accounts": [
{
"balance": 2000,
"currency": "USD",
"id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0",
"name": "My Online Trading Account",

1
test/import/ok/derived-currency.json

@ -5,7 +5,6 @@
},
"accounts": [
{
"balance": 2000,
"currency": "USD",
"id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0",
"name": "My Online Trading Account",

1
test/import/ok/sample.json

@ -5,7 +5,6 @@
},
"accounts": [
{
"balance": 2000,
"balances": [
{
"date": "2024-12-31T00:00:00.000Z",

Loading…
Cancel
Save