From 3332f58376639a8c313f8cdc14bb3c6e82d4b4fd Mon Sep 17 00:00:00 2001
From: Neil <55785687+carkom@users.noreply.github.com>
Date: Mon, 24 Jun 2024 20:08:59 +0100
Subject: [PATCH] Custom Reports: Adjust Net values (#2871)
* Add Net value
* notes
* fix
* revert changes
* balanceTypeOpType
* lint fix
* add net numbers
* bar fix
* nit fixes and fix clicks
* remove abs
---
.../src/components/reports/ReportOptions.ts | 2 +
.../src/components/reports/ReportSummary.tsx | 17 ++++---
.../src/components/reports/disabledList.ts | 8 ++--
.../components/reports/graphs/AreaGraph.tsx | 25 +++++++++--
.../components/reports/graphs/BarGraph.tsx | 35 ++++++++++++---
.../components/reports/graphs/DonutGraph.tsx | 9 ++--
.../components/reports/graphs/LineGraph.tsx | 7 ++-
.../reports/graphs/StackedBarGraph.tsx | 8 +++-
.../components/reports/graphs/showActivity.ts | 12 ++---
.../reports/graphs/tableGraph/ReportTable.tsx | 3 +-
.../graphs/tableGraph/ReportTableHeader.tsx | 7 ++-
.../graphs/tableGraph/ReportTableList.tsx | 2 +
.../graphs/tableGraph/ReportTableRow.tsx | 7 ++-
.../graphs/tableGraph/ReportTableTotals.tsx | 2 +
.../reports/reports/CustomReport.tsx | 5 ++-
.../reports/spreadsheets/calculateLegend.ts | 3 +-
.../spreadsheets/custom-spreadsheet.ts | 45 ++++++++++++++++---
.../reports/spreadsheets/filterEmptyRows.ts | 7 ++-
.../spreadsheets/grouped-spreadsheet.ts | 25 ++++++++++-
.../reports/spreadsheets/recalculate.ts | 14 ++++--
.../loot-core/src/types/models/reports.d.ts | 13 ++++++
upcoming-release-notes/2871.md | 6 +++
22 files changed, 210 insertions(+), 52 deletions(-)
create mode 100644 upcoming-release-notes/2871.md
diff --git a/packages/desktop-client/src/components/reports/ReportOptions.ts b/packages/desktop-client/src/components/reports/ReportOptions.ts
index 25fc2555182..6fe42586be1 100644
--- a/packages/desktop-client/src/components/reports/ReportOptions.ts
+++ b/packages/desktop-client/src/components/reports/ReportOptions.ts
@@ -35,6 +35,8 @@ const balanceTypeOptions = [
{ description: 'Payment', format: 'totalDebts' as const },
{ description: 'Deposit', format: 'totalAssets' as const },
{ description: 'Net', format: 'totalTotals' as const },
+ { description: 'Net Payment', format: 'netDebts' as const },
+ { description: 'Net Deposit', format: 'netAssets' as const },
];
const groupByOptions = [
diff --git a/packages/desktop-client/src/components/reports/ReportSummary.tsx b/packages/desktop-client/src/components/reports/ReportSummary.tsx
index 9e25d548cfe..88968e67a0a 100644
--- a/packages/desktop-client/src/components/reports/ReportSummary.tsx
+++ b/packages/desktop-client/src/components/reports/ReportSummary.tsx
@@ -6,7 +6,10 @@ import {
integerToCurrency,
amountToInteger,
} from 'loot-core/src/shared/util';
-import { type DataEntity } from 'loot-core/src/types/models/reports';
+import {
+ type balanceTypeOpType,
+ type DataEntity,
+} from 'loot-core/src/types/models/reports';
import { theme, styles } from '../../style';
import { Text } from '../common/Text';
@@ -19,7 +22,7 @@ type ReportSummaryProps = {
startDate: string;
endDate: string;
data: DataEntity;
- balanceTypeOp: 'totalDebts' | 'totalAssets' | 'totalTotals';
+ balanceTypeOp: balanceTypeOpType;
interval: string;
intervalsCount: number;
};
@@ -33,9 +36,13 @@ export function ReportSummary({
intervalsCount,
}: ReportSummaryProps) {
const net =
- Math.abs(data.totalDebts) > Math.abs(data.totalAssets)
- ? 'PAYMENT'
- : 'DEPOSIT';
+ balanceTypeOp === 'netAssets'
+ ? 'DEPOSIT'
+ : balanceTypeOp === 'netDebts'
+ ? 'PAYMENT'
+ : Math.abs(data.totalDebts) > Math.abs(data.totalAssets)
+ ? 'PAYMENT'
+ : 'DEPOSIT';
const average = amountToInteger(data[balanceTypeOp]) / intervalsCount;
return (
)}
+ {['netAssets'].includes(balanceTypeOp) && (
+
+ )}
+ {['netDebts'].includes(balanceTypeOp) && (
+
+ )}
{['totalTotals'].includes(balanceTypeOp) && (
)}
+ {['netAssets'].includes(balanceTypeOp) && (
+
+ )}
+ {['netDebts'].includes(balanceTypeOp) && (
+
+ )}
{['totalTotals'].includes(balanceTypeOp) && (
{
- if (balanceTypeOp === 'totalDebts') {
- return -1 * obj.totalDebts;
- } else {
+ if (balanceTypeOp === 'totalTotals' && groupBy === 'Interval') {
return obj.totalAssets;
}
+
+ if (['totalDebts', 'netDebts'].includes(balanceTypeOp)) {
+ return -1 * obj[balanceTypeOp];
+ }
+
+ return obj[balanceTypeOp];
};
const longestLabelLength = data[splitData]
diff --git a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
index 3eab0f182d4..d6b02490b9f 100644
--- a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
@@ -4,7 +4,10 @@ import React, { useState } from 'react';
import { PieChart, Pie, Cell, Sector, ResponsiveContainer } from 'recharts';
import { amountToCurrency } from 'loot-core/src/shared/util';
-import { type DataEntity } from 'loot-core/src/types/models/reports';
+import {
+ type balanceTypeOpType,
+ type DataEntity,
+} from 'loot-core/src/types/models/reports';
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
import { useAccounts } from '../../../hooks/useAccounts';
@@ -181,7 +184,7 @@ type DonutGraphProps = {
data: DataEntity;
filters: RuleConditionEntity[];
groupBy: string;
- balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals';
+ balanceTypeOp: balanceTypeOpType;
compact?: boolean;
viewLabels: boolean;
showHiddenCategories?: boolean;
@@ -209,7 +212,7 @@ export function DonutGraph({
const [pointer, setPointer] = useState('');
const getVal = obj => {
- if (balanceTypeOp === 'totalDebts') {
+ if (['totalDebts', 'netDebts'].includes(balanceTypeOp)) {
return -1 * obj[balanceTypeOp];
} else {
return obj[balanceTypeOp];
diff --git a/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx b/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx
index d47575f88b9..14c53ad28e1 100644
--- a/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx
@@ -16,7 +16,10 @@ import {
amountToCurrency,
amountToCurrencyNoDecimal,
} from 'loot-core/src/shared/util';
-import { type DataEntity } from 'loot-core/types/models/reports';
+import {
+ type balanceTypeOpType,
+ type DataEntity,
+} from 'loot-core/types/models/reports';
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
import { useAccounts } from '../../../hooks/useAccounts';
@@ -115,7 +118,7 @@ type LineGraphProps = {
filters: RuleConditionEntity[];
groupBy: string;
compact?: boolean;
- balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals';
+ balanceTypeOp: balanceTypeOpType;
showHiddenCategories?: boolean;
showOffBudget?: boolean;
interval?: string;
diff --git a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
index 81463d147d8..309fa8618dc 100644
--- a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
@@ -17,7 +17,10 @@ import {
amountToCurrency,
amountToCurrencyNoDecimal,
} from 'loot-core/src/shared/util';
-import { type DataEntity } from 'loot-core/src/types/models/reports';
+import {
+ type balanceTypeOpType,
+ type DataEntity,
+} from 'loot-core/src/types/models/reports';
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
import { useAccounts } from '../../../hooks/useAccounts';
@@ -144,7 +147,7 @@ type StackedBarGraphProps = {
groupBy: string;
compact?: boolean;
viewLabels: boolean;
- balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals';
+ balanceTypeOp: balanceTypeOpType;
showHiddenCategories?: boolean;
showOffBudget?: boolean;
interval?: string;
@@ -194,6 +197,7 @@ export function StackedBarGraph({
data={data.intervalData}
margin={{ top: 0, right: 0, left: leftMargin, bottom: 10 }}
style={{ cursor: pointer }}
+ stackOffset="sign" //stacked by sign
>
{(!isNarrowWidth || !compact) && (
;
handleScroll: UIEventHandler;
groupBy: string;
- balanceTypeOp: 'totalDebts' | 'totalTotals' | 'totalAssets';
+ balanceTypeOp: balanceTypeOpType;
data: DataEntity;
filters?: RuleConditionEntity[];
mode: string;
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx
index 2dea557dea7..926beef7ecc 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx
@@ -1,6 +1,9 @@
import React, { type RefObject, type UIEventHandler } from 'react';
-import { type IntervalEntity } from 'loot-core/src/types/models/reports';
+import {
+ type balanceTypeOpType,
+ type IntervalEntity,
+} from 'loot-core/src/types/models/reports';
import { theme } from '../../../../style';
import { type CSSProperties } from '../../../../style/types';
@@ -12,7 +15,7 @@ type ReportTableHeaderProps = {
groupBy: string;
interval: string;
data: IntervalEntity[];
- balanceTypeOp: 'totalDebts' | 'totalTotals' | 'totalAssets';
+ balanceTypeOp: balanceTypeOpType;
headerScrollRef: RefObject;
handleScroll: UIEventHandler;
compact: boolean;
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx
index f3ba6bad8a2..e26b51367d5 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx
@@ -38,6 +38,8 @@ export function ReportTableList({
date: interval.date,
totalAssets: interval.totalAssets,
totalDebts: interval.totalDebts,
+ netAssets: interval.netAssets,
+ netDebts: interval.netDebts,
totalTotals: interval.totalTotals,
intervalData: [],
categories: [],
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableRow.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableRow.tsx
index c18cf54c9ca..11a8dea359e 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableRow.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableRow.tsx
@@ -5,7 +5,10 @@ import {
amountToInteger,
integerToCurrency,
} from 'loot-core/src/shared/util';
-import { type GroupedEntity } from 'loot-core/types/models/reports';
+import {
+ type balanceTypeOpType,
+ type GroupedEntity,
+} from 'loot-core/types/models/reports';
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
import { useAccounts } from '../../../../hooks/useAccounts';
@@ -20,7 +23,7 @@ import { showActivity } from '../showActivity';
type ReportTableRowProps = {
item: GroupedEntity;
- balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals';
+ balanceTypeOp: balanceTypeOpType;
groupBy: string;
mode: string;
filters?: RuleConditionEntity[];
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableTotals.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableTotals.tsx
index 8690fc709e5..ed192f0c4eb 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableTotals.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableTotals.tsx
@@ -85,6 +85,8 @@ export function ReportTableTotals({
intervalData: data.intervalData,
totalAssets: data.totalAssets,
totalDebts: data.totalDebts,
+ netAssets: data.netAssets,
+ netDebts: data.netDebts,
totalTotals: data.totalTotals,
};
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.tsx b/packages/desktop-client/src/components/reports/reports/CustomReport.tsx
index 2fb2a375c1b..edeba3fbf22 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReport.tsx
+++ b/packages/desktop-client/src/components/reports/reports/CustomReport.tsx
@@ -8,6 +8,7 @@ import * as monthUtils from 'loot-core/src/shared/months';
import { amountToCurrency } from 'loot-core/src/shared/util';
import { type CategoryEntity } from 'loot-core/types/models/category';
import {
+ type balanceTypeOpType,
type CustomReportEntity,
type DataEntity,
} from 'loot-core/types/models/reports';
@@ -248,7 +249,7 @@ export function CustomReport() {
}
}, [interval, startDate, endDate, firstDayOfWeekIdx]);
- const balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals' =
+ const balanceTypeOp: balanceTypeOpType =
ReportOptions.balanceTypeMap.get(balanceType) || 'totalDebts';
const payees = usePayees();
const accounts = useAccounts();
@@ -692,7 +693,7 @@ export function CustomReport() {
right={
- {amountToCurrency(Math.abs(data[balanceTypeOp]))}
+ {amountToCurrency(data[balanceTypeOp])}
}
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts b/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts
index 7ada7dec8d9..93a80014fee 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts
@@ -2,6 +2,7 @@ import {
type LegendEntity,
type IntervalEntity,
type GroupedEntity,
+ type balanceTypeOpType,
} from 'loot-core/src/types/models/reports';
import { theme } from '../../../style';
@@ -12,7 +13,7 @@ export function calculateLegend(
calcDataFiltered: GroupedEntity[],
groupBy: string,
graphType?: string,
- balanceTypeOp?: 'totalAssets' | 'totalDebts' | 'totalTotals',
+ balanceTypeOp?: balanceTypeOpType,
): LegendEntity[] {
const colorScale = getColorScale('qualitative');
const chooseData =
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/custom-spreadsheet.ts b/packages/desktop-client/src/components/reports/spreadsheets/custom-spreadsheet.ts
index 0ad83924bf9..86a2fd6ebeb 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/custom-spreadsheet.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/custom-spreadsheet.ts
@@ -13,6 +13,7 @@ import {
type CategoryGroupEntity,
} from 'loot-core/src/types/models';
import {
+ type balanceTypeOpType,
type DataEntity,
type GroupedEntity,
type IntervalEntity,
@@ -46,7 +47,7 @@ export type createCustomSpreadsheetProps = {
showHiddenCategories: boolean;
showUncategorized: boolean;
groupBy?: string;
- balanceTypeOp?: 'totalAssets' | 'totalDebts' | 'totalTotals';
+ balanceTypeOp?: balanceTypeOpType;
payees?: PayeeEntity[];
accounts?: AccountEntity[];
graphType?: string;
@@ -153,11 +154,16 @@ export function createCustomSpreadsheet({
let totalAssets = 0;
let totalDebts = 0;
+ let netAssets = 0;
+ let netDebts = 0;
const intervalData = intervals.reduce(
(arr: IntervalEntity[], intervalItem, index) => {
let perIntervalAssets = 0;
let perIntervalDebts = 0;
+ let perIntervalNetAssets = 0;
+ let perIntervalNetDebts = 0;
+ let perIntervalTotals = 0;
const stacked: Record = {};
groupByList.map(item => {
@@ -193,20 +199,43 @@ export function createCustomSpreadsheet({
.reduce((a, v) => (a = a + v.amount), 0);
perIntervalDebts += intervalDebts;
+ const netAmounts = intervalAssets + intervalDebts;
+
if (balanceTypeOp === 'totalAssets') {
stackAmounts += intervalAssets;
}
if (balanceTypeOp === 'totalDebts') {
- stackAmounts += intervalDebts;
+ stackAmounts += Math.abs(intervalDebts);
+ }
+ if (balanceTypeOp === 'netAssets') {
+ stackAmounts += netAmounts > 0 ? netAmounts : 0;
+ }
+ if (balanceTypeOp === 'netDebts') {
+ stackAmounts = netAmounts < 0 ? Math.abs(netAmounts) : 0;
+ }
+ if (balanceTypeOp === 'totalTotals') {
+ stackAmounts += netAmounts;
}
if (stackAmounts !== 0) {
- stacked[item.name] = integerToAmount(Math.abs(stackAmounts));
+ stacked[item.name] = integerToAmount(stackAmounts);
}
+ perIntervalNetAssets =
+ netAmounts > 0
+ ? perIntervalNetAssets + netAmounts
+ : perIntervalNetAssets;
+ perIntervalNetDebts =
+ netAmounts < 0
+ ? perIntervalNetDebts + netAmounts
+ : perIntervalNetDebts;
+ perIntervalTotals += netAmounts;
+
return null;
});
totalAssets += perIntervalAssets;
totalDebts += perIntervalDebts;
+ netAssets += perIntervalNetAssets;
+ netDebts += perIntervalNetDebts;
arr.push({
date: d.format(
@@ -219,9 +248,11 @@ export function createCustomSpreadsheet({
index + 1 === intervals.length
? endDate
: monthUtils.subDays(intervals[index + 1], 1),
- totalDebts: integerToAmount(perIntervalDebts),
totalAssets: integerToAmount(perIntervalAssets),
- totalTotals: integerToAmount(perIntervalDebts + perIntervalAssets),
+ totalDebts: integerToAmount(perIntervalDebts),
+ netAssets: integerToAmount(perIntervalNetAssets),
+ netDebts: integerToAmount(perIntervalNetDebts),
+ totalTotals: integerToAmount(perIntervalTotals),
});
return arr;
@@ -262,8 +293,10 @@ export function createCustomSpreadsheet({
legend,
startDate,
endDate,
- totalDebts: integerToAmount(totalDebts),
totalAssets: integerToAmount(totalAssets),
+ totalDebts: integerToAmount(totalDebts),
+ netAssets: integerToAmount(netAssets),
+ netDebts: integerToAmount(netDebts),
totalTotals: integerToAmount(totalAssets + totalDebts),
});
setDataCheck?.(true);
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/filterEmptyRows.ts b/packages/desktop-client/src/components/reports/spreadsheets/filterEmptyRows.ts
index b133a67da13..922696e9cf7 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/filterEmptyRows.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/filterEmptyRows.ts
@@ -1,4 +1,7 @@
-import { type GroupedEntity } from 'loot-core/src/types/models/reports';
+import {
+ type balanceTypeOpType,
+ type GroupedEntity,
+} from 'loot-core/src/types/models/reports';
export function filterEmptyRows({
showEmpty,
@@ -7,7 +10,7 @@ export function filterEmptyRows({
}: {
showEmpty: boolean;
data: GroupedEntity;
- balanceTypeOp?: 'totalAssets' | 'totalDebts' | 'totalTotals';
+ balanceTypeOp?: balanceTypeOpType;
}): boolean {
let showHide: boolean;
if (balanceTypeOp === 'totalTotals') {
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/grouped-spreadsheet.ts b/packages/desktop-client/src/components/reports/spreadsheets/grouped-spreadsheet.ts
index ed3048d291d..414bb93a8b2 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/grouped-spreadsheet.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/grouped-spreadsheet.ts
@@ -111,11 +111,16 @@ export function createGroupedSpreadsheet({
group => {
let totalAssets = 0;
let totalDebts = 0;
+ let netAssets = 0;
+ let netDebts = 0;
const intervalData = intervals.reduce(
(arr: IntervalEntity[], intervalItem) => {
let groupedAssets = 0;
let groupedDebts = 0;
+ let groupedNetAssets = 0;
+ let groupedNetDebts = 0;
+ let groupedTotals = 0;
if (!group.categories) {
return [];
@@ -151,16 +156,32 @@ export function createGroupedSpreadsheet({
)
.reduce((a, v) => (a = a + v.amount), 0);
groupedDebts += intervalDebts;
+
+ const intervalTotals = intervalAssets + intervalDebts;
+
+ groupedNetAssets =
+ intervalTotals > 0
+ ? groupedNetAssets + intervalTotals
+ : groupedNetAssets;
+ groupedNetDebts =
+ intervalTotals < 0
+ ? groupedNetDebts + intervalTotals
+ : groupedNetDebts;
+ groupedTotals += intervalTotals;
});
totalAssets += groupedAssets;
totalDebts += groupedDebts;
+ netAssets += groupedNetAssets;
+ netDebts += groupedNetDebts;
arr.push({
date: intervalItem,
totalAssets: integerToAmount(groupedAssets),
totalDebts: integerToAmount(groupedDebts),
- totalTotals: integerToAmount(groupedDebts + groupedAssets),
+ netAssets: integerToAmount(groupedNetAssets),
+ netDebts: integerToAmount(groupedNetDebts),
+ totalTotals: integerToAmount(groupedTotals),
});
return arr;
@@ -191,6 +212,8 @@ export function createGroupedSpreadsheet({
name: group.name,
totalAssets: integerToAmount(totalAssets),
totalDebts: integerToAmount(totalDebts),
+ netAssets: integerToAmount(netAssets),
+ netDebts: integerToAmount(netDebts),
totalTotals: integerToAmount(totalAssets + totalDebts),
intervalData,
categories:
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/recalculate.ts b/packages/desktop-client/src/components/reports/spreadsheets/recalculate.ts
index 3f4bc44b7b4..d0dc1e1c9f9 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/recalculate.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/recalculate.ts
@@ -73,14 +73,18 @@ export function recalculate({
.reduce((a, v) => (a = a + v.amount), 0);
totalDebts += intervalDebts;
+ const intervalTotals = intervalAssets + intervalDebts;
+
const change = last
- ? intervalAssets + intervalDebts - amountToInteger(last.totalTotals)
+ ? intervalTotals - amountToInteger(last.totalTotals)
: 0;
arr.push({
totalAssets: integerToAmount(intervalAssets),
totalDebts: integerToAmount(intervalDebts),
- totalTotals: integerToAmount(intervalAssets + intervalDebts),
+ netAssets: intervalTotals > 0 ? integerToAmount(intervalTotals) : 0,
+ netDebts: intervalTotals < 0 ? integerToAmount(intervalTotals) : 0,
+ totalTotals: integerToAmount(intervalTotals),
change,
intervalStartDate: index === 0 ? startDate : intervalItem,
intervalEndDate:
@@ -94,12 +98,16 @@ export function recalculate({
[],
);
+ const totalTotals = totalAssets + totalDebts;
+
return {
id: item.id || '',
name: item.name,
totalAssets: integerToAmount(totalAssets),
totalDebts: integerToAmount(totalDebts),
- totalTotals: integerToAmount(totalAssets + totalDebts),
+ netAssets: totalTotals > 0 ? integerToAmount(totalTotals) : 0,
+ netDebts: totalTotals < 0 ? integerToAmount(totalTotals) : 0,
+ totalTotals: integerToAmount(totalTotals),
intervalData,
};
}
diff --git a/packages/loot-core/src/types/models/reports.d.ts b/packages/loot-core/src/types/models/reports.d.ts
index d7e04a5f816..da645278614 100644
--- a/packages/loot-core/src/types/models/reports.d.ts
+++ b/packages/loot-core/src/types/models/reports.d.ts
@@ -25,6 +25,13 @@ export interface CustomReportEntity {
tombstone?: boolean;
}
+export type balanceTypeOpType =
+ | 'totalAssets'
+ | 'totalDebts'
+ | 'totalTotals'
+ | 'netAssets'
+ | 'netDebts';
+
export type SpendingMonthEntity = Record<
string | number,
{
@@ -68,6 +75,8 @@ export interface DataEntity {
endDate?: string;
totalDebts: number;
totalAssets: number;
+ netAssets: number;
+ netDebts: number;
totalTotals: number;
}
@@ -84,6 +93,8 @@ export type IntervalEntity = {
intervalEndDate?: string;
totalAssets: number;
totalDebts: number;
+ netAssets: number;
+ netDebts: number;
totalTotals: number;
};
@@ -95,6 +106,8 @@ export interface GroupedEntity {
totalAssets: number;
totalDebts: number;
totalTotals: number;
+ netAssets: number;
+ netDebts: number;
categories?: GroupedEntity[];
}
diff --git a/upcoming-release-notes/2871.md b/upcoming-release-notes/2871.md
new file mode 100644
index 00000000000..6488461265f
--- /dev/null
+++ b/upcoming-release-notes/2871.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [carkom]
+---
+
+Custom reports - rework "net" numbers to work more intuitively and allow for greater customization