Round totals rather than expense by expense (#88)

* do balance rounding only on full balances rather than on every expense

* use "public balances" calculated from reimbursements to show on balance page

* fixes for totals that did not work as expected

* prettier
This commit is contained in:
Lauri Vuorela
2024-02-13 20:35:57 +01:00
committed by GitHub
parent 5b65b8f049
commit f7a13a0436
2 changed files with 37 additions and 6 deletions

View File

@@ -9,7 +9,11 @@ import {
CardTitle, CardTitle,
} from '@/components/ui/card' } from '@/components/ui/card'
import { getGroupExpenses } from '@/lib/api' import { getGroupExpenses } from '@/lib/api'
import { getBalances, getSuggestedReimbursements } from '@/lib/balances' import {
getBalances,
getPublicBalances,
getSuggestedReimbursements,
} from '@/lib/balances'
import { Metadata } from 'next' import { Metadata } from 'next'
import { notFound } from 'next/navigation' import { notFound } from 'next/navigation'
@@ -28,6 +32,7 @@ export default async function GroupPage({
const expenses = await getGroupExpenses(groupId) const expenses = await getGroupExpenses(groupId)
const balances = getBalances(expenses) const balances = getBalances(expenses)
const reimbursements = getSuggestedReimbursements(balances) const reimbursements = getSuggestedReimbursements(balances)
const publicBalances = getPublicBalances(reimbursements)
return ( return (
<> <>
@@ -40,7 +45,7 @@ export default async function GroupPage({
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<BalancesList <BalancesList
balances={balances} balances={publicBalances}
participants={group.participants} participants={group.participants}
currency={group.currency} currency={group.currency}
/> />

View File

@@ -24,7 +24,6 @@ export function getBalances(
if (!balances[paidBy]) balances[paidBy] = { paid: 0, paidFor: 0, total: 0 } if (!balances[paidBy]) balances[paidBy] = { paid: 0, paidFor: 0, total: 0 }
balances[paidBy].paid += expense.amount balances[paidBy].paid += expense.amount
balances[paidBy].total += expense.amount
const totalPaidForShares = paidFors.reduce( const totalPaidForShares = paidFors.reduce(
(sum, paidFor) => sum + paidFor.shares, (sum, paidFor) => sum + paidFor.shares,
@@ -46,13 +45,40 @@ export function getBalances(
const dividedAmount = isLast const dividedAmount = isLast
? remaining ? remaining
: Math.floor((expense.amount * shares) / totalShares) : (expense.amount * shares) / totalShares
remaining -= dividedAmount remaining -= dividedAmount
balances[paidFor.participantId].paidFor += dividedAmount balances[paidFor.participantId].paidFor += dividedAmount
balances[paidFor.participantId].total -= dividedAmount
}) })
} }
// rounding and add total
for (const participantId in balances) {
// add +0 to avoid negative zeros
balances[participantId].paidFor =
Math.round(balances[participantId].paidFor) + 0
balances[participantId].paid = Math.round(balances[participantId].paid) + 0
balances[participantId].total =
balances[participantId].paid - balances[participantId].paidFor
}
return balances
}
export function getPublicBalances(reimbursements: Reimbursement[]): Balances {
const balances: Balances = {}
reimbursements.forEach((reimbursement) => {
if (!balances[reimbursement.from])
balances[reimbursement.from] = { paid: 0, paidFor: 0, total: 0 }
if (!balances[reimbursement.to])
balances[reimbursement.to] = { paid: 0, paidFor: 0, total: 0 }
balances[reimbursement.from].paidFor += reimbursement.amount
balances[reimbursement.from].total -= reimbursement.amount
balances[reimbursement.to].paid += reimbursement.amount
balances[reimbursement.to].total += reimbursement.amount
})
return balances return balances
} }
@@ -86,5 +112,5 @@ export function getSuggestedReimbursements(
balancesArray.shift() balancesArray.shift()
} }
} }
return reimbursements.filter(({ amount }) => amount !== 0) return reimbursements.filter(({ amount }) => Math.round(amount) + 0 !== 0)
} }