Skip to content

Commit

Permalink
Round totals rather than expense by expense (#88)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
justcallmelarry committed Feb 13, 2024
1 parent 5b65b8f commit f7a13a0
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
9 changes: 7 additions & 2 deletions src/app/groups/[groupId]/balances/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import {
CardTitle,
} from '@/components/ui/card'
import { getGroupExpenses } from '@/lib/api'
import { getBalances, getSuggestedReimbursements } from '@/lib/balances'
import {
getBalances,
getPublicBalances,
getSuggestedReimbursements,
} from '@/lib/balances'
import { Metadata } from 'next'
import { notFound } from 'next/navigation'

Expand All @@ -28,6 +32,7 @@ export default async function GroupPage({
const expenses = await getGroupExpenses(groupId)
const balances = getBalances(expenses)
const reimbursements = getSuggestedReimbursements(balances)
const publicBalances = getPublicBalances(reimbursements)

return (
<>
Expand All @@ -40,7 +45,7 @@ export default async function GroupPage({
</CardHeader>
<CardContent>
<BalancesList
balances={balances}
balances={publicBalances}
participants={group.participants}
currency={group.currency}
/>
Expand Down
34 changes: 30 additions & 4 deletions src/lib/balances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export function getBalances(

if (!balances[paidBy]) balances[paidBy] = { paid: 0, paidFor: 0, total: 0 }
balances[paidBy].paid += expense.amount
balances[paidBy].total += expense.amount

const totalPaidForShares = paidFors.reduce(
(sum, paidFor) => sum + paidFor.shares,
Expand All @@ -46,13 +45,40 @@ export function getBalances(

const dividedAmount = isLast
? remaining
: Math.floor((expense.amount * shares) / totalShares)
: (expense.amount * shares) / totalShares
remaining -= 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
}

Expand Down Expand Up @@ -86,5 +112,5 @@ export function getSuggestedReimbursements(
balancesArray.shift()
}
}
return reimbursements.filter(({ amount }) => amount !== 0)
return reimbursements.filter(({ amount }) => Math.round(amount) + 0 !== 0)
}

0 comments on commit f7a13a0

Please sign in to comment.