Files
spliit/src/lib/totals.ts
Daniel Thiem 728e072376 Add computed shares per expense to fix #127 (#269)
* Added computed expenses per balance to fix #127

* add missing import that got lost during merge

* if we are in percentage mode or amount mode, the shares have to be multiplied by 100
2025-04-19 15:16:37 -04:00

79 lines
2.2 KiB
TypeScript

import { getGroupExpenses } from '@/lib/api'
export function getTotalGroupSpending(
expenses: NonNullable<Awaited<ReturnType<typeof getGroupExpenses>>>,
): number {
return expenses.reduce(
(total, expense) =>
expense.isReimbursement ? total : total + expense.amount,
0,
)
}
export function getTotalActiveUserPaidFor(
activeUserId: string | null,
expenses: NonNullable<Awaited<ReturnType<typeof getGroupExpenses>>>,
): number {
return expenses.reduce(
(total, expense) =>
expense.paidBy.id === activeUserId && !expense.isReimbursement
? total + expense.amount
: total,
0,
)
}
type Expense = NonNullable<Awaited<ReturnType<typeof getGroupExpenses>>>[number]
export function calculateShare(
participantId: string | null,
expense: Pick<
Expense,
'amount' | 'paidFor' | 'splitMode' | 'isReimbursement'
>,
): number {
if (expense.isReimbursement) return 0
const paidFors = expense.paidFor
const userPaidFor = paidFors.find(
(paidFor) => paidFor.participant.id === participantId,
)
if (!userPaidFor) return 0
const shares = Number(userPaidFor.shares)
switch (expense.splitMode) {
case 'EVENLY':
// Divide the total expense evenly among all participants
return expense.amount / paidFors.length
case 'BY_AMOUNT':
// Directly add the user's share if the split mode is BY_AMOUNT
return shares
case 'BY_PERCENTAGE':
// Calculate the user's share based on their percentage of the total expense
return (expense.amount * shares) / 10000 // Assuming shares are out of 10000 for percentage
case 'BY_SHARES':
// Calculate the user's share based on their shares relative to the total shares
const totalShares = paidFors.reduce(
(sum, paidFor) => sum + Number(paidFor.shares),
0,
)
return (expense.amount * shares) / totalShares
default:
return 0
}
}
export function getTotalActiveUserShare(
activeUserId: string | null,
expenses: NonNullable<Awaited<ReturnType<typeof getGroupExpenses>>>,
): number {
const total = expenses.reduce(
(sum, expense) => sum + calculateShare(activeUserId, expense),
0,
)
return parseFloat(total.toFixed(2))
}