Browse Source

Merge fb90fc63d0 into 449eaa1baa

pull/6981/merge
Sjohn21 13 hours ago
committed by GitHub
parent
commit
991933c459
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      apps/api/src/app/admin/admin.service.ts
  2. 2
      apps/api/src/app/app.module.ts
  3. 41
      apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts
  4. 14
      apps/api/src/app/endpoints/asset-profiles/asset-profiles.module.ts
  5. 95
      apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts
  6. 2
      libs/common/src/lib/dtos/index.ts
  7. 16
      libs/common/src/lib/dtos/update-asset-profile-data.dto.ts

1
apps/api/src/app/admin/admin.service.ts

@ -593,6 +593,7 @@ export class AdminService {
assetClass: assetClass as AssetClass, assetClass: assetClass as AssetClass,
assetSubClass: assetSubClass as AssetSubClass, assetSubClass: assetSubClass as AssetSubClass,
countries: countries as Prisma.JsonArray, countries: countries as Prisma.JsonArray,
holdings: holdings as Prisma.JsonArray,
name: name as string, name: name as string,
sectors: sectors as Prisma.JsonArray, sectors: sectors as Prisma.JsonArray,
url: url as string url: url as string

2
apps/api/src/app/app.module.ts

@ -38,6 +38,7 @@ import { AuthModule } from './auth/auth.module';
import { CacheModule } from './cache/cache.module'; import { CacheModule } from './cache/cache.module';
import { AiModule } from './endpoints/ai/ai.module'; import { AiModule } from './endpoints/ai/ai.module';
import { ApiKeysModule } from './endpoints/api-keys/api-keys.module'; import { ApiKeysModule } from './endpoints/api-keys/api-keys.module';
import { AssetProfilesModule } from './endpoints/asset-profiles/asset-profiles.module';
import { AssetsModule } from './endpoints/assets/assets.module'; import { AssetsModule } from './endpoints/assets/assets.module';
import { BenchmarksModule } from './endpoints/benchmarks/benchmarks.module'; import { BenchmarksModule } from './endpoints/benchmarks/benchmarks.module';
import { GhostfolioModule } from './endpoints/data-providers/ghostfolio/ghostfolio.module'; import { GhostfolioModule } from './endpoints/data-providers/ghostfolio/ghostfolio.module';
@ -69,6 +70,7 @@ import { UserModule } from './user/user.module';
ActivitiesModule, ActivitiesModule,
AiModule, AiModule,
ApiKeysModule, ApiKeysModule,
AssetProfilesModule,
AssetModule, AssetModule,
AssetsModule, AssetsModule,
AuthDeviceModule, AuthDeviceModule,

41
apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts

@ -0,0 +1,41 @@
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor';
import { UpdateAssetProfileDataDto } from '@ghostfolio/common/dtos';
import { EnhancedSymbolProfile } from '@ghostfolio/common/interfaces';
import { permissions } from '@ghostfolio/common/permissions';
import {
Body,
Controller,
Param,
Patch,
UseGuards,
UseInterceptors
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { DataSource } from '@prisma/client';
import { AssetProfilesService } from './asset-profiles.service';
@Controller('asset-profiles')
export class AssetProfilesController {
public constructor(
private readonly assetProfilesService: AssetProfilesService
) {}
@HasPermission(permissions.accessAdminControl)
@Patch(':dataSource/:symbol')
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
@UseInterceptors(TransformDataSourceInRequestInterceptor)
public async updateAssetProfileData(
@Body() assetProfileData: UpdateAssetProfileDataDto,
@Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string
): Promise<EnhancedSymbolProfile> {
return this.assetProfilesService.updateAssetProfileData(
{ dataSource, symbol },
assetProfileData
);
}
}

14
apps/api/src/app/endpoints/asset-profiles/asset-profiles.module.ts

@ -0,0 +1,14 @@
import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module';
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module';
import { Module } from '@nestjs/common';
import { AssetProfilesController } from './asset-profiles.controller';
import { AssetProfilesService } from './asset-profiles.service';
@Module({
controllers: [AssetProfilesController],
imports: [SymbolProfileModule, TransformDataSourceInRequestModule],
providers: [AssetProfilesService]
})
export class AssetProfilesModule {}

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

@ -0,0 +1,95 @@
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
import { UpdateAssetProfileDataDto } from '@ghostfolio/common/dtos';
import {
AssetProfileIdentifier,
EnhancedSymbolProfile
} from '@ghostfolio/common/interfaces';
import { Injectable, NotFoundException } from '@nestjs/common';
import { DataSource, Prisma } from '@prisma/client';
@Injectable()
export class AssetProfilesService {
public constructor(
private readonly symbolProfileService: SymbolProfileService
) {}
public async updateAssetProfileData(
{ dataSource, symbol }: AssetProfileIdentifier,
assetProfileData: UpdateAssetProfileDataDto
): Promise<EnhancedSymbolProfile> {
const [assetProfile] = await this.symbolProfileService.getSymbolProfiles([
{
dataSource,
symbol
}
]);
if (!assetProfile) {
throw new NotFoundException(
`Asset profile with data source ${dataSource} and symbol ${symbol} not found`
);
}
const data = this.getAssetProfileDataUpdate(assetProfileData);
if (Object.keys(data).length === 0) {
return assetProfile;
}
await this.symbolProfileService.updateSymbolProfile(
{
dataSource,
symbol
},
dataSource === DataSource.MANUAL
? data
: {
SymbolProfileOverrides: {
upsert: {
create: data,
update: data
}
}
}
);
const [updatedAssetProfile] =
await this.symbolProfileService.getSymbolProfiles([
{
dataSource,
symbol
}
]);
return updatedAssetProfile;
}
private getAssetProfileDataUpdate({
countries,
holdings,
sectors
}: UpdateAssetProfileDataDto): Pick<
Prisma.SymbolProfileUpdateInput,
'countries' | 'holdings' | 'sectors'
> {
const data: Pick<
Prisma.SymbolProfileUpdateInput,
'countries' | 'holdings' | 'sectors'
> = {};
if (countries !== undefined) {
data.countries = countries as Prisma.JsonArray;
}
if (holdings !== undefined) {
data.holdings = holdings as Prisma.JsonArray;
}
if (sectors !== undefined) {
data.sectors = sectors as Prisma.JsonArray;
}
return data;
}
}

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

@ -13,6 +13,7 @@ import { DeleteOwnUserDto } from './delete-own-user.dto';
import { TransferBalanceDto } from './transfer-balance.dto'; import { TransferBalanceDto } from './transfer-balance.dto';
import { UpdateAccessDto } from './update-access.dto'; import { UpdateAccessDto } from './update-access.dto';
import { UpdateAccountDto } from './update-account.dto'; import { UpdateAccountDto } from './update-account.dto';
import { UpdateAssetProfileDataDto } from './update-asset-profile-data.dto';
import { UpdateAssetProfileDto } from './update-asset-profile.dto'; import { UpdateAssetProfileDto } from './update-asset-profile.dto';
import { UpdateBulkMarketDataDto } from './update-bulk-market-data.dto'; import { UpdateBulkMarketDataDto } from './update-bulk-market-data.dto';
import { UpdateMarketDataDto } from './update-market-data.dto'; import { UpdateMarketDataDto } from './update-market-data.dto';
@ -39,6 +40,7 @@ export {
TransferBalanceDto, TransferBalanceDto,
UpdateAccessDto, UpdateAccessDto,
UpdateAccountDto, UpdateAccountDto,
UpdateAssetProfileDataDto,
UpdateAssetProfileDto, UpdateAssetProfileDto,
UpdateBulkMarketDataDto, UpdateBulkMarketDataDto,
UpdateMarketDataDto, UpdateMarketDataDto,

16
libs/common/src/lib/dtos/update-asset-profile-data.dto.ts

@ -0,0 +1,16 @@
import { Prisma } from '@prisma/client';
import { IsArray, IsOptional } from 'class-validator';
export class UpdateAssetProfileDataDto {
@IsArray()
@IsOptional()
countries?: Prisma.InputJsonArray;
@IsArray()
@IsOptional()
holdings?: Prisma.InputJsonArray;
@IsArray()
@IsOptional()
sectors?: Prisma.InputJsonArray;
}
Loading…
Cancel
Save