diff --git a/src/app/components/Portfolio/Report/PnLComponent.tsx b/src/app/components/Portfolio/Report/PnLComponent.tsx new file mode 100644 index 0000000..4fd1c3d --- /dev/null +++ b/src/app/components/Portfolio/Report/PnLComponent.tsx @@ -0,0 +1,93 @@ +import { Box, HStack, Spacer, Text, VStack } from "@chakra-ui/react"; +import { default as React } from "react"; +import { ReportEntry, TradesSummary } from "../../../../routers/reports.types"; +import Number from "../../Number/Number"; + +type Props = { theReports: ReportEntry[] }; + +type PnlCallback = (ReportEntry) => number; + +const PnLs: Record = { + ["Trade"]: (tradesSummary: TradesSummary) => tradesSummary.stocksPnLInBase, + ["TradeOption"]: (tradesSummary: TradesSummary) => tradesSummary.optionsPnLInBase, + ["Bond"]: (tradesSummary: TradesSummary) => tradesSummary.bondPnLInBase, +}; + +const _compareReports = (a: ReportEntry, b: ReportEntry): number => { + let result = a.year - b.year; + if (!result) result = a.month - b.month; + return result; +}; + +const OneAssetTable = ({ + theReports, + assetType, + ..._rest +}: { + theReports: ReportEntry[]; + assetType: string; +}): React.ReactNode => { + let pnlTotal = 0; + const addToTotal = (pnl: number): React.ReactNode => { + pnlTotal += pnl; + return <>; + }; + + return ( + <> + + {theReports + .filter((report) => PnLs[assetType](report.tradesSummary)) + .map((report) => ( + + + {report.year}-{report.month} + + + {addToTotal(PnLs[assetType](report.tradesSummary))} + + ))} + + Subtotal + + + + + ); +}; + +/** + * Dividends table component + * @param theReports Tax reports to summarize. Assume their summaries are sorted by date + * @returns + */ +const PnL = ({ theReports, ..._rest }: Props): React.ReactNode => { + return ( + <> + + + Country + Month + + P&L + + + + {Object.keys(PnLs).map((assetType) => ( + + {assetType} + + + ))} + + Total + + p + report.tradesSummary.totalPnL, 0)} width="120px" /> + + + + + ); +}; + +export default PnL; diff --git a/src/app/components/Portfolio/Report/ReportSummary.tsx b/src/app/components/Portfolio/Report/ReportSummary.tsx index 65a04ff..383bb58 100644 --- a/src/app/components/Portfolio/Report/ReportSummary.tsx +++ b/src/app/components/Portfolio/Report/ReportSummary.tsx @@ -5,6 +5,7 @@ import { ReportEntry } from "../../../../routers/reports.types"; import Dividends from "./DividendsComponent"; import Fees from "./FeeComponent"; import Interests from "./InterestsComponent"; +import PnL from "./PnLComponent"; import { ReportLink } from "./links"; type Props = Record; @@ -42,6 +43,9 @@ const ReportSummary: FunctionComponent = ({ ..._rest }): React.ReactNode

Fees

+ +

P&L

+ ); }; diff --git a/src/routers/statements.utils.ts b/src/routers/statements.utils.ts index bd2a89c..d1bd264 100644 --- a/src/routers/statements.utils.ts +++ b/src/routers/statements.utils.ts @@ -125,6 +125,7 @@ export const statementModelToStatementEntry = (item: Statement): Promise { + if (!thisStatement) throw Error(`BondStatement ${item.id} not found!`); let country: string; if (thisStatement!.country) country = thisStatement!.country; else if (item.stock.isin) country = item.stock.isin.substring(0, 2);