Merge branch 'main' of gitea.suda.codes:giteauser/ghostfolio-mirror
This commit is contained in:
commit
9a2ca9cd08
6
.husky/pre-commit
Normal file
6
.husky/pre-commit
Normal file
@ -0,0 +1,6 @@
|
||||
# Run linting and stop the commit process if any errors are found
|
||||
# --quiet suppresses warnings (temporary until all warnings are fixed)
|
||||
npm run lint --quiet || exit 1
|
||||
|
||||
# Check formatting on modified and uncommitted files, stop the commit if issues are found
|
||||
npm run format:check --uncommitted || exit 1
|
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- Set up a git-hook via `husky` to lint and format the changes before a commit
|
||||
|
||||
### Fixed
|
||||
|
||||
- Handled an exception in the historical market data gathering of derived currencies
|
||||
|
@ -14,7 +14,6 @@
|
||||
1. Run `npm install`
|
||||
1. Run `docker compose --env-file ./.env -f docker/docker-compose.dev.yml up -d` to start [PostgreSQL](https://www.postgresql.org) and [Redis](https://redis.io)
|
||||
1. Run `npm run database:setup` to initialize the database schema
|
||||
1. Run `git config core.hooksPath ./git-hooks/` to setup git hooks
|
||||
1. Start the [server](#start-server) and the [client](#start-client)
|
||||
1. Open https://localhost:4200/en in your browser
|
||||
1. Create a new user via _Get Started_ (this first user will get the role `ADMIN`)
|
||||
|
@ -45,7 +45,6 @@ import type {
|
||||
AccountWithValue,
|
||||
DateRange,
|
||||
GroupBy,
|
||||
Market,
|
||||
RequestWithUser,
|
||||
UserWithSettings
|
||||
} from '@ghostfolio/common/types';
|
||||
@ -582,15 +581,11 @@ export class PortfolioService {
|
||||
};
|
||||
}
|
||||
|
||||
let markets: {
|
||||
[key in Market]: {
|
||||
name: string;
|
||||
value: number;
|
||||
};
|
||||
};
|
||||
let markets: PortfolioDetails['markets'];
|
||||
let marketsAdvanced: PortfolioDetails['marketsAdvanced'];
|
||||
|
||||
if (withMarkets) {
|
||||
markets = this.getAggregatedMarkets(holdings);
|
||||
({ markets, marketsAdvanced } = this.getAggregatedMarkets(holdings));
|
||||
}
|
||||
|
||||
let summary: PortfolioSummary;
|
||||
@ -615,6 +610,7 @@ export class PortfolioService {
|
||||
hasErrors,
|
||||
holdings,
|
||||
markets,
|
||||
marketsAdvanced,
|
||||
platforms,
|
||||
summary
|
||||
};
|
||||
@ -1248,24 +1244,67 @@ export class PortfolioService {
|
||||
private getAggregatedMarkets(holdings: {
|
||||
[symbol: string]: PortfolioPosition;
|
||||
}): {
|
||||
[key in Market]: { name: string; value: number };
|
||||
markets: PortfolioDetails['markets'];
|
||||
marketsAdvanced: PortfolioDetails['marketsAdvanced'];
|
||||
} {
|
||||
const markets = {
|
||||
const markets: PortfolioDetails['markets'] = {
|
||||
[UNKNOWN_KEY]: {
|
||||
name: UNKNOWN_KEY,
|
||||
value: 0
|
||||
id: UNKNOWN_KEY,
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
developedMarkets: {
|
||||
name: 'developedMarkets',
|
||||
value: 0
|
||||
id: 'developedMarkets',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
emergingMarkets: {
|
||||
name: 'emergingMarkets',
|
||||
value: 0
|
||||
id: 'emergingMarkets',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
otherMarkets: {
|
||||
name: 'otherMarkets',
|
||||
value: 0
|
||||
id: 'otherMarkets',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
}
|
||||
};
|
||||
|
||||
const marketsAdvanced: PortfolioDetails['marketsAdvanced'] = {
|
||||
[UNKNOWN_KEY]: {
|
||||
id: UNKNOWN_KEY,
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
asiaPacific: {
|
||||
id: 'asiaPacific',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
emergingMarkets: {
|
||||
id: 'emergingMarkets',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
europe: {
|
||||
id: 'europe',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
japan: {
|
||||
id: 'japan',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
northAmerica: {
|
||||
id: 'northAmerica',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
},
|
||||
otherMarkets: {
|
||||
id: 'otherMarkets',
|
||||
valueInBaseCurrency: 0,
|
||||
valueInPercentage: 0
|
||||
}
|
||||
};
|
||||
|
||||
@ -1274,31 +1313,73 @@ export class PortfolioService {
|
||||
|
||||
if (position.assetClass !== AssetClass.LIQUIDITY) {
|
||||
if (position.countries.length > 0) {
|
||||
markets.developedMarkets.value +=
|
||||
markets.developedMarkets.valueInBaseCurrency +=
|
||||
position.markets.developedMarkets * value;
|
||||
markets.emergingMarkets.value +=
|
||||
markets.emergingMarkets.valueInBaseCurrency +=
|
||||
position.markets.emergingMarkets * value;
|
||||
markets.otherMarkets.value += position.markets.otherMarkets * value;
|
||||
markets.otherMarkets.valueInBaseCurrency +=
|
||||
position.markets.otherMarkets * value;
|
||||
|
||||
marketsAdvanced.asiaPacific.valueInBaseCurrency +=
|
||||
position.marketsAdvanced.asiaPacific * value;
|
||||
marketsAdvanced.emergingMarkets.valueInBaseCurrency +=
|
||||
position.marketsAdvanced.emergingMarkets * value;
|
||||
marketsAdvanced.europe.valueInBaseCurrency +=
|
||||
position.marketsAdvanced.europe * value;
|
||||
marketsAdvanced.japan.valueInBaseCurrency +=
|
||||
position.marketsAdvanced.japan * value;
|
||||
marketsAdvanced.northAmerica.valueInBaseCurrency +=
|
||||
position.marketsAdvanced.northAmerica * value;
|
||||
marketsAdvanced.otherMarkets.valueInBaseCurrency +=
|
||||
position.marketsAdvanced.otherMarkets * value;
|
||||
} else {
|
||||
markets[UNKNOWN_KEY].value += value;
|
||||
markets[UNKNOWN_KEY].valueInBaseCurrency += value;
|
||||
marketsAdvanced[UNKNOWN_KEY].valueInBaseCurrency += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const marketsTotal =
|
||||
markets.developedMarkets.value +
|
||||
markets.emergingMarkets.value +
|
||||
markets.otherMarkets.value +
|
||||
markets[UNKNOWN_KEY].value;
|
||||
markets.developedMarkets.valueInBaseCurrency +
|
||||
markets.emergingMarkets.valueInBaseCurrency +
|
||||
markets.otherMarkets.valueInBaseCurrency +
|
||||
markets[UNKNOWN_KEY].valueInBaseCurrency;
|
||||
|
||||
markets.developedMarkets.value =
|
||||
markets.developedMarkets.value / marketsTotal;
|
||||
markets.emergingMarkets.value =
|
||||
markets.emergingMarkets.value / marketsTotal;
|
||||
markets.otherMarkets.value = markets.otherMarkets.value / marketsTotal;
|
||||
markets[UNKNOWN_KEY].value = markets[UNKNOWN_KEY].value / marketsTotal;
|
||||
markets.developedMarkets.valueInPercentage =
|
||||
markets.developedMarkets.valueInBaseCurrency / marketsTotal;
|
||||
markets.emergingMarkets.valueInPercentage =
|
||||
markets.emergingMarkets.valueInBaseCurrency / marketsTotal;
|
||||
markets.otherMarkets.valueInPercentage =
|
||||
markets.otherMarkets.valueInBaseCurrency / marketsTotal;
|
||||
markets[UNKNOWN_KEY].valueInPercentage =
|
||||
markets[UNKNOWN_KEY].valueInBaseCurrency / marketsTotal;
|
||||
|
||||
return markets;
|
||||
const marketsAdvancedTotal =
|
||||
marketsAdvanced.asiaPacific.valueInBaseCurrency +
|
||||
marketsAdvanced.emergingMarkets.valueInBaseCurrency +
|
||||
marketsAdvanced.europe.valueInBaseCurrency +
|
||||
marketsAdvanced.japan.valueInBaseCurrency +
|
||||
marketsAdvanced.northAmerica.valueInBaseCurrency +
|
||||
marketsAdvanced.otherMarkets.valueInBaseCurrency +
|
||||
marketsAdvanced[UNKNOWN_KEY].valueInBaseCurrency;
|
||||
|
||||
marketsAdvanced.asiaPacific.valueInPercentage =
|
||||
marketsAdvanced.asiaPacific.valueInBaseCurrency / marketsAdvancedTotal;
|
||||
marketsAdvanced.emergingMarkets.valueInPercentage =
|
||||
marketsAdvanced.emergingMarkets.valueInBaseCurrency /
|
||||
marketsAdvancedTotal;
|
||||
marketsAdvanced.europe.valueInPercentage =
|
||||
marketsAdvanced.europe.valueInBaseCurrency / marketsAdvancedTotal;
|
||||
marketsAdvanced.japan.valueInPercentage =
|
||||
marketsAdvanced.japan.valueInBaseCurrency / marketsAdvancedTotal;
|
||||
marketsAdvanced.northAmerica.valueInPercentage =
|
||||
marketsAdvanced.northAmerica.valueInBaseCurrency / marketsAdvancedTotal;
|
||||
marketsAdvanced.otherMarkets.valueInPercentage =
|
||||
marketsAdvanced.otherMarkets.valueInBaseCurrency / marketsAdvancedTotal;
|
||||
marketsAdvanced[UNKNOWN_KEY].valueInPercentage =
|
||||
marketsAdvanced[UNKNOWN_KEY].valueInBaseCurrency / marketsAdvancedTotal;
|
||||
|
||||
return { markets, marketsAdvanced };
|
||||
}
|
||||
|
||||
private async getCashPositions({
|
||||
|
@ -1,26 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Will check if "npm run format" is run before executing.
|
||||
# Called by "git commit" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message if
|
||||
# it wants to stop the commit.
|
||||
|
||||
echo "Running npm run format"
|
||||
|
||||
# Run the command and loop over its output
|
||||
FILES_TO_STAGE=""
|
||||
i=0
|
||||
while IFS= read -r line; do
|
||||
# Process each line here
|
||||
((i++))
|
||||
if [ $i -le 2 ]; then
|
||||
continue
|
||||
fi
|
||||
if [[ $line == Done* ]]; then
|
||||
break
|
||||
fi
|
||||
FILES_TO_STAGE="$FILES_TO_STAGE $line"
|
||||
|
||||
done < <(npm run format)
|
||||
git add $FILES_TO_STAGE
|
||||
echo "Files formatted. Committing..."
|
@ -2,7 +2,7 @@ import {
|
||||
PortfolioPosition,
|
||||
PortfolioSummary
|
||||
} from '@ghostfolio/common/interfaces';
|
||||
import { Market } from '@ghostfolio/common/types';
|
||||
import { Market, MarketAdvanced } from '@ghostfolio/common/types';
|
||||
|
||||
export interface PortfolioDetails {
|
||||
accounts: {
|
||||
@ -17,8 +17,16 @@ export interface PortfolioDetails {
|
||||
holdings: { [symbol: string]: PortfolioPosition };
|
||||
markets?: {
|
||||
[key in Market]: {
|
||||
name: string;
|
||||
value: number;
|
||||
id: Market;
|
||||
valueInBaseCurrency: number;
|
||||
valueInPercentage: number;
|
||||
};
|
||||
};
|
||||
marketsAdvanced?: {
|
||||
[key in MarketAdvanced]: {
|
||||
id: MarketAdvanced;
|
||||
valueInBaseCurrency: number;
|
||||
valueInPercentage: number;
|
||||
};
|
||||
};
|
||||
platforms: {
|
||||
|
16
package-lock.json
generated
16
package-lock.json
generated
@ -143,6 +143,7 @@
|
||||
"eslint-plugin-cypress": "2.15.1",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-storybook": "0.6.15",
|
||||
"husky": "9.1.6",
|
||||
"jest": "29.7.0",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"jest-preset-angular": "14.1.0",
|
||||
@ -20653,6 +20654,21 @@
|
||||
"node": ">=8.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/husky": {
|
||||
"version": "9.1.6",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz",
|
||||
"integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"husky": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
}
|
||||
},
|
||||
"node_modules/hyperdyperid": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz",
|
||||
|
@ -33,10 +33,11 @@
|
||||
"format:check": "nx format:check",
|
||||
"format:write": "nx format:write",
|
||||
"help": "nx help",
|
||||
"lint": "nx lint",
|
||||
"lint": "nx run-many --target=lint --all",
|
||||
"ng": "nx",
|
||||
"nx": "nx",
|
||||
"postinstall": "prisma generate",
|
||||
"prepare": "husky",
|
||||
"prisma": "prisma",
|
||||
"replace-placeholders-in-build": "node ./replace.build.js",
|
||||
"start": "node dist/apps/api/main",
|
||||
@ -188,6 +189,7 @@
|
||||
"eslint-plugin-cypress": "2.15.1",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-storybook": "0.6.15",
|
||||
"husky": "9.1.6",
|
||||
"jest": "29.7.0",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"jest-preset-angular": "14.1.0",
|
||||
|
Loading…
x
Reference in New Issue
Block a user