Browse Source

Add business logic and tests for stock splits

pull/7568/head
Thomas Kaul 2 weeks ago
parent
commit
7e7d7df82b
  1. 12
      apps/api/src/app/activities/activities.service.ts
  2. 17
      apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.spec.ts
  3. 24
      apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts

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

@ -984,17 +984,13 @@ export class ActivitiesService {
* Returns the id of every user who has an activity for the given asset * Returns the id of every user who has an activity for the given asset
* profile, including draft activities and activities of excluded accounts * profile, including draft activities and activities of excluded accounts
*/ */
public async getUserIdsByAssetProfile({ public async getUserIdsBySymbolProfileId(
dataSource, symbolProfileId: string
symbol ): Promise<string[]> {
}: AssetProfileIdentifier): Promise<string[]> {
const activitiesByUser = await this.prismaService.order.groupBy({ const activitiesByUser = await this.prismaService.order.groupBy({
by: ['userId'], by: ['userId'],
where: { where: {
SymbolProfile: { symbolProfileId
dataSource,
symbol
}
} }
}); });

17
apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.spec.ts

@ -15,7 +15,7 @@ describe('AssetProfilesService', () => {
let emit: jest.Mock; let emit: jest.Mock;
let finished: jest.Mock; let finished: jest.Mock;
let gatherSymbol: jest.Mock; let gatherSymbol: jest.Mock;
let getUserIdsByAssetProfile: jest.Mock; let getUserIdsBySymbolProfileId: jest.Mock;
let upsert: jest.Mock; let upsert: jest.Mock;
beforeEach(() => { beforeEach(() => {
@ -23,11 +23,11 @@ describe('AssetProfilesService', () => {
emit = jest.fn(); emit = jest.fn();
finished = jest.fn().mockResolvedValue(undefined); finished = jest.fn().mockResolvedValue(undefined);
gatherSymbol = jest.fn().mockResolvedValue([{ finished }]); gatherSymbol = jest.fn().mockResolvedValue([{ finished }]);
getUserIdsByAssetProfile = jest.fn().mockResolvedValue([]); getUserIdsBySymbolProfileId = jest.fn().mockResolvedValue([]);
upsert = jest.fn(); upsert = jest.fn();
assetProfilesService = new AssetProfilesService( assetProfilesService = new AssetProfilesService(
{ getUserIdsByAssetProfile } as unknown as ActivitiesService, { getUserIdsBySymbolProfileId } as unknown as ActivitiesService,
{ {
deleteById, deleteById,
upsert upsert
@ -73,7 +73,7 @@ describe('AssetProfilesService', () => {
it('invalidates portfolio snapshots for users holding the asset', async () => { it('invalidates portfolio snapshots for users holding the asset', async () => {
upsert.mockResolvedValue({} as AssetProfileSplit); upsert.mockResolvedValue({} as AssetProfileSplit);
getUserIdsByAssetProfile.mockResolvedValue(['user-1', 'user-2']); getUserIdsBySymbolProfileId.mockResolvedValue(['user-1', 'user-2']);
await assetProfilesService.createSplit({ await assetProfilesService.createSplit({
dataSource: DataSource.YAHOO, dataSource: DataSource.YAHOO,
@ -85,10 +85,7 @@ describe('AssetProfilesService', () => {
}); });
await flushPendingPromises(); await flushPendingPromises();
expect(getUserIdsByAssetProfile).toHaveBeenCalledWith({ expect(getUserIdsBySymbolProfileId).toHaveBeenCalledWith('profile-id');
dataSource: DataSource.YAHOO,
symbol: 'AAPL'
});
expect(emit.mock.calls.map(([, event]) => event.getUserId())).toEqual([ expect(emit.mock.calls.map(([, event]) => event.getUserId())).toEqual([
'user-1', 'user-1',
'user-2' 'user-2'
@ -105,7 +102,7 @@ describe('AssetProfilesService', () => {
}) })
); );
upsert.mockResolvedValue({} as AssetProfileSplit); upsert.mockResolvedValue({} as AssetProfileSplit);
getUserIdsByAssetProfile.mockResolvedValue(['user-1']); getUserIdsBySymbolProfileId.mockResolvedValue(['user-1']);
await assetProfilesService.createSplit({ await assetProfilesService.createSplit({
dataSource: DataSource.YAHOO, dataSource: DataSource.YAHOO,
@ -148,7 +145,7 @@ describe('AssetProfilesService', () => {
it('deletes an existing split using its profile scope', async () => { it('deletes an existing split using its profile scope', async () => {
deleteById.mockResolvedValue(true); deleteById.mockResolvedValue(true);
getUserIdsByAssetProfile.mockResolvedValue(['user-1']); getUserIdsBySymbolProfileId.mockResolvedValue(['user-1']);
await expect( await expect(
assetProfilesService.deleteSplit({ assetProfilesService.deleteSplit({

24
apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts

@ -67,7 +67,8 @@ export class AssetProfilesService {
await this.gatherSymbolAndEmitPortfolioChangedEvents({ await this.gatherSymbolAndEmitPortfolioChangedEvents({
dataSource, dataSource,
symbol symbol,
symbolProfileId
}); });
return assetProfileSplit; return assetProfileSplit;
@ -93,7 +94,8 @@ export class AssetProfilesService {
await this.gatherSymbolAndEmitPortfolioChangedEvents({ await this.gatherSymbolAndEmitPortfolioChangedEvents({
dataSource, dataSource,
symbol symbol,
symbolProfileId
}); });
} }
@ -438,14 +440,9 @@ export class AssetProfilesService {
return assetProfile; return assetProfile;
} }
private async emitPortfolioChangedEvents({ private async emitPortfolioChangedEvents(symbolProfileId: string) {
dataSource, const userIds =
symbol await this.activitiesService.getUserIdsBySymbolProfileId(symbolProfileId);
}: AssetProfileIdentifier) {
const userIds = await this.activitiesService.getUserIdsByAssetProfile({
dataSource,
symbol
});
for (const userId of userIds) { for (const userId of userIds) {
this.eventEmitter.emit( this.eventEmitter.emit(
@ -463,8 +460,9 @@ export class AssetProfilesService {
*/ */
private async gatherSymbolAndEmitPortfolioChangedEvents({ private async gatherSymbolAndEmitPortfolioChangedEvents({
dataSource, dataSource,
symbol symbol,
}: AssetProfileIdentifier) { symbolProfileId
}: { symbolProfileId: string } & AssetProfileIdentifier) {
const jobs = await this.dataGatheringService.gatherSymbol({ const jobs = await this.dataGatheringService.gatherSymbol({
dataSource, dataSource,
symbol symbol
@ -475,7 +473,7 @@ export class AssetProfilesService {
return job.finished(); return job.finished();
}) })
).then(() => { ).then(() => {
return this.emitPortfolioChangedEvents({ dataSource, symbol }); return this.emitPortfolioChangedEvents(symbolProfileId);
}); });
} }

Loading…
Cancel
Save