Browse Source

Refine stock split activity handling and dependencies

pull/7568/head
David Requeno 3 weeks ago
parent
commit
aead44e8d4
  1. 28
      apps/api/src/app/activities/activities.service.spec.ts
  2. 4
      apps/api/src/app/activities/activities.service.ts
  3. 8
      apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts
  4. 2
      apps/api/src/app/portfolio/portfolio.service.spec.ts
  5. 5
      apps/api/src/services/asset-profile-split/asset-profile-split.helper.ts

28
apps/api/src/app/activities/activities.service.spec.ts

@ -4,6 +4,10 @@ import {
assetProfileDummyData
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
import { AssetProfileSplitService } from '@ghostfolio/api/services/asset-profile-split/asset-profile-split.service';
import {
INVESTMENT_ACTIVITY_TYPES,
NON_INVESTMENT_ACTIVITY_TYPES
} from '@ghostfolio/common/config';
import { parseDate } from '@ghostfolio/common/helper';
import { Activity, Filter } from '@ghostfolio/common/interfaces';
@ -24,6 +28,7 @@ describe('ActivitiesService', () => {
activitiesService = new ActivitiesService(
null,
accountService as unknown as AccountService,
{ getSplitsBySymbolProfileIds } as unknown as AssetProfileSplitService,
null,
null,
null,
@ -32,8 +37,7 @@ describe('ActivitiesService', () => {
null,
null,
null,
null,
{ getSplitsBySymbolProfileIds } as unknown as AssetProfileSplitService
null
);
});
@ -150,8 +154,8 @@ describe('ActivitiesService', () => {
expect(result.activities[0].unitPrice).toBe(100);
});
it.each(['DIVIDEND', 'INTEREST', 'LIABILITY'])(
'preserves the value of %s activities',
it.each(INVESTMENT_ACTIVITY_TYPES)(
'adjusts %s activities',
async (type) => {
const activity = createActivity({ symbol: 'AAPL' });
activity.type = type as Activity['type'];
@ -166,6 +170,22 @@ describe('ActivitiesService', () => {
}
);
it.each(NON_INVESTMENT_ACTIVITY_TYPES)(
'leaves %s activities unchanged',
async (type) => {
const activity = createActivity({ symbol: 'AAPL' });
activity.type = type as Activity['type'];
const result = await getAdjustedActivity(activity, [
createSplit('2021-01-01', 2, 1)
]);
expect(result).toBe(activity);
expect(result.quantity).toBe(10);
expect(result.unitPrice).toBe(100);
}
);
it('loads and applies splits to standard activities while preserving filters', async () => {
const activity = createActivity({ symbol: 'AAPL' });
const filters = [{ id: 'AAPL', type: 'SYMBOL' }] as Filter[];

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

@ -68,6 +68,7 @@ export class ActivitiesService {
public constructor(
private readonly accountBalanceService: AccountBalanceService,
private readonly accountService: AccountService,
private readonly assetProfileSplitService: AssetProfileSplitService,
private readonly benchmarkService: BenchmarkService,
private readonly dataGatheringService: DataGatheringService,
private readonly dataProviderService: DataProviderService,
@ -76,8 +77,7 @@ export class ActivitiesService {
private readonly marketDataService: MarketDataService,
private readonly prismaService: PrismaService,
private readonly symbolProfileService: SymbolProfileService,
private readonly tagService: TagService,
private readonly assetProfileSplitService: AssetProfileSplitService
private readonly tagService: TagService
) {}
public areCashActivitiesExcludedByFilters(filters: Filter[] = []) {

8
apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts

@ -125,6 +125,9 @@ describe('PortfolioCalculator', () => {
activitiesService = new ActivitiesService(
accountBalanceService,
accountService,
{
getSplitsBySymbolProfileIds: jest.fn().mockResolvedValue(new Map())
} as unknown as AssetProfileSplitService,
null,
null,
dataProviderService,
@ -133,10 +136,7 @@ describe('PortfolioCalculator', () => {
null,
null,
null,
null,
{
getSplitsBySymbolProfileIds: jest.fn().mockResolvedValue(new Map())
} as unknown as AssetProfileSplitService
null
);
portfolioSnapshotService = new PortfolioSnapshotService(null, null);

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

@ -68,13 +68,13 @@ describe('PortfolioService', () => {
accountService,
null,
null,
null,
dataProviderService,
null,
exchangeRateDataService,
null,
null,
null,
null,
null
);

5
apps/api/src/services/asset-profile-split/asset-profile-split.helper.ts

@ -1,3 +1,4 @@
import { INVESTMENT_ACTIVITY_TYPES } from '@ghostfolio/common/config';
import { resetHours } from '@ghostfolio/common/helper';
import { Activity } from '@ghostfolio/common/interfaces';
@ -9,6 +10,10 @@ export function adjustActivityBySplits(
activity: Activity,
splits: AssetProfileSplit[]
): Activity {
if (!INVESTMENT_ACTIVITY_TYPES.includes(activity.type)) {
return activity;
}
const activityDate = resetHours(activity.date);
let splitFactor = new Big(1);

Loading…
Cancel
Save