Browse Source

Support migrating asset profile to MANUAL data source

pull/7376/head
Thomas Kaul 1 month ago
parent
commit
0ffd06ecd3
  1. 32
      apps/api/src/app/admin/admin.service.ts
  2. 9
      apps/api/src/services/symbol-profile/symbol-profile.service.ts
  3. 55
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  4. 11
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

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

@ -19,7 +19,8 @@ import {
AdminData,
AdminUserResponse,
AdminUsersResponse,
AssetProfileIdentifier
AssetProfileIdentifier,
Holding
} from '@ghostfolio/common/interfaces';
import { PropertyKey } from '@ghostfolio/common/types';
@ -283,6 +284,35 @@ export class AdminService {
)
]);
if (DataSource[newDataSource.toString()] === DataSource.MANUAL) {
await Promise.all([
this.symbolProfileService.deleteAssetProfileOverrides({
dataSource: DataSource.MANUAL,
symbol: newSymbol as string
}),
this.symbolProfileService.updateSymbolProfile(
{
dataSource: DataSource.MANUAL,
symbol: newSymbol as string
},
{
assetClass,
assetSubClass,
countries,
name,
sectors,
url,
holdings: (holdings as unknown as Holding[])?.map((holding) => {
return {
name: holding.name,
weight: holding.allocationInPercentage
};
})
}
)
]);
}
const [updatedAssetProfile] =
await this.symbolProfileService.getSymbolProfiles([
{

9
apps/api/src/services/symbol-profile/symbol-profile.service.ts

@ -35,6 +35,15 @@ export class SymbolProfileService {
});
}
public async deleteAssetProfileOverrides({
dataSource,
symbol
}: AssetProfileIdentifier) {
return this.prismaService.assetProfileOverrides.deleteMany({
where: { symbolProfile: { dataSource, symbol } }
});
}
public async deleteById(id: string) {
return this.prismaService.symbolProfile.delete({
where: { id }

55
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts

@ -75,6 +75,7 @@ import {
AssetClass,
AssetSubClass,
DataGatheringFrequency,
DataSource,
MarketData,
Prisma,
SymbolProfile
@ -467,6 +468,60 @@ export class GfAssetProfileDialogComponent implements OnInit {
this.dialogRef.close();
}
protected onConvertToManualDataSource() {
const convertedAssetProfile: UpdateAssetProfileDto = {
assetClass: this.assetProfile?.assetClass ?? undefined,
assetSubClass: this.assetProfile?.assetSubClass ?? undefined,
countries: this.assetProfile?.countries?.map(({ code, weight }) => {
return { code, weight };
}),
dataSource: DataSource.MANUAL,
holdings: this.assetProfile?.holdings?.map(
({ allocationInPercentage, name }) => {
return { allocationInPercentage, name };
}
),
name: this.assetProfile?.name ?? undefined,
sectors: this.assetProfile?.sectors?.map(({ name, weight }) => {
return { name, weight };
}),
symbol: crypto.randomUUID(),
url: this.assetProfile?.url ?? undefined
};
this.adminService
.patchAssetProfile(
{
dataSource: this.data.dataSource,
symbol: this.data.symbol
},
convertedAssetProfile
)
.pipe(
catchError(() => {
this.snackBar.open(
'😞 ' +
$localize`An error occurred while converting the asset profile to ${DataSource.MANUAL}.`,
undefined,
{
duration: ms('3 seconds')
}
);
return EMPTY;
}),
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {
const newAssetProfileIdentifier = {
dataSource: convertedAssetProfile.dataSource,
symbol: convertedAssetProfile.symbol
};
this.dialogRef.close(newAssetProfileIdentifier);
});
}
protected onDeleteProfileData({
dataSource,
symbol

11
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html

@ -162,6 +162,17 @@
<ng-container i18n>Cancel</ng-container>
</button>
</form>
@if (data.dataSource !== 'MANUAL') {
<p class="my-1" i18n>or</p>
<button
color="accent"
mat-flat-button
type="button"
(click)="onConvertToManualDataSource()"
>
<ng-container i18n>Convert to MANUAL</ng-container>
</button>
}
</div>
} @else {
<div class="col-6 mb-3">

Loading…
Cancel
Save