Direct Settlement
This commit is contained in:
+10
-2
@@ -48,8 +48,10 @@ import net.helcel.cowspent.model.Transaction
|
||||
import net.helcel.cowspent.model.UserItem
|
||||
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
||||
import net.helcel.cowspent.util.SupportUtil
|
||||
import net.helcel.cowspent.util.SupportUtil.SETTLE_DIRECT
|
||||
import net.helcel.cowspent.util.SupportUtil.SETTLE_OPTIMAL
|
||||
import net.helcel.cowspent.util.SupportUtil.settleBills
|
||||
import net.helcel.cowspent.util.SupportUtil.settleBillsDirect
|
||||
|
||||
@Composable
|
||||
fun ProjectSettlementDialogContent(
|
||||
@@ -60,10 +62,12 @@ fun ProjectSettlementDialogContent(
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val centerNoneStr = stringResource(R.string.center_none)
|
||||
val centerDirectStr = stringResource(R.string.center_none_direct)
|
||||
val memberList = remember(proj.id) { db.getMembersOfProject(proj.id, null) }
|
||||
val userList = remember(memberList, centerNoneStr) {
|
||||
val userList = remember(memberList, centerNoneStr, centerDirectStr) {
|
||||
buildList {
|
||||
add(UserItem(SETTLE_OPTIMAL, centerNoneStr))
|
||||
add(UserItem(SETTLE_DIRECT, centerDirectStr))
|
||||
addAll(memberList.map { UserItem(it.id, it.name) })
|
||||
}
|
||||
}
|
||||
@@ -91,7 +95,11 @@ fun ProjectSettlementDialogContent(
|
||||
}
|
||||
|
||||
val transactions = remember(selectedMemberId, membersBalance, membersSortedByName) {
|
||||
settleBills(membersSortedByName, membersBalance, selectedMemberId)
|
||||
if (selectedMemberId == SETTLE_DIRECT) {
|
||||
settleBillsDirect(membersSortedByName, db.getBillsOfProject(proj.id))
|
||||
} else {
|
||||
settleBills(membersSortedByName, membersBalance, selectedMemberId)
|
||||
}
|
||||
}
|
||||
|
||||
ProjectSettlementUI(
|
||||
|
||||
@@ -141,7 +141,7 @@ object SupportUtil {
|
||||
membersBalance[b.payerId] = balPayer + amount
|
||||
val paid = membersPaid[b.payerId] ?: 0.0
|
||||
membersPaid[b.payerId] = paid + amount
|
||||
|
||||
|
||||
var nbOwerShares = 0.0
|
||||
for (bo in b.billOwers) {
|
||||
nbOwerShares += membersWeight[bo.memberId] ?: 0.0
|
||||
@@ -167,6 +167,39 @@ object SupportUtil {
|
||||
}
|
||||
|
||||
const val SETTLE_OPTIMAL: Long = 0
|
||||
const val SETTLE_DIRECT: Long = -1
|
||||
|
||||
@JvmStatic
|
||||
fun settleBillsDirect(members: List<DBMember>, bills: List<DBBill>): List<Transaction> {
|
||||
val membersWeight = members.associate { it.id to it.weight }
|
||||
// owed[debtor][creditor] = total the debtor owes the creditor over all bills
|
||||
val owed = HashMap<Long, HashMap<Long, Double>>()
|
||||
|
||||
for (b in bills) {
|
||||
if (b.state == DBBill.STATE_DELETED) continue
|
||||
val nbOwerShares = b.billOwers.sumOf { membersWeight[it.memberId] ?: 0.0 }
|
||||
if (nbOwerShares <= 0.0) continue
|
||||
for (bo in b.billOwers) {
|
||||
if (bo.memberId == b.payerId) continue
|
||||
val share = b.amount / nbOwerShares * (membersWeight[bo.memberId] ?: 0.0)
|
||||
val row = owed.getOrPut(bo.memberId) { HashMap() }
|
||||
row[b.payerId] = (row[b.payerId] ?: 0.0) + share
|
||||
}
|
||||
}
|
||||
|
||||
val results: MutableList<Transaction> = ArrayList()
|
||||
for (debtor in members) {
|
||||
for (creditor in members) {
|
||||
if (debtor.id == creditor.id) continue
|
||||
val net = (owed[debtor.id]?.get(creditor.id) ?: 0.0) -
|
||||
(owed[creditor.id]?.get(debtor.id) ?: 0.0)
|
||||
if (round2(net) > 0.0) {
|
||||
results.add(Transaction(debtor.id, creditor.id, round2(net)))
|
||||
}
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun settleBills(
|
||||
@@ -233,11 +266,11 @@ object SupportUtil {
|
||||
if (cd1.balance < cd2.balance) 1 else -1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (c in crediters) {
|
||||
Log.e(SupportUtil::class.java.simpleName, "* " + c.memberId + " : " + c.balance)
|
||||
}
|
||||
|
||||
|
||||
debiters.sortWith { cd2, cd1 ->
|
||||
if (cd1.balance == cd2.balance) {
|
||||
0
|
||||
|
||||
@@ -209,6 +209,7 @@
|
||||
|
||||
<!-- Settlement -->
|
||||
<string name="center_none">Keine (optimal)</string>
|
||||
<string name="center_none_direct">Keine (direkt)</string>
|
||||
<string name="settle_who">Wer zahlt</string>
|
||||
<string name="settle_to_whom">An wen</string>
|
||||
<string name="settle_how_much">Betrag</string>
|
||||
|
||||
@@ -210,6 +210,7 @@
|
||||
|
||||
<!-- Settlement -->
|
||||
<string name="center_none">Ninguno (óptimo)</string>
|
||||
<string name="center_none_direct">Ninguno (directo)</string>
|
||||
<string name="settle_who">Quién paga</string>
|
||||
<string name="settle_to_whom">A quién</string>
|
||||
<string name="settle_how_much">Importe</string>
|
||||
|
||||
@@ -213,6 +213,7 @@
|
||||
|
||||
<!-- Settlement -->
|
||||
<string name="center_none">Aucun (optimal)</string>
|
||||
<string name="center_none_direct">Aucun (direct)</string>
|
||||
<string name="settle_who">Qui paie</string>
|
||||
<string name="settle_to_whom">À qui</string>
|
||||
<string name="settle_how_much">Montant</string>
|
||||
|
||||
@@ -209,6 +209,7 @@
|
||||
|
||||
<!-- Settlement -->
|
||||
<string name="center_none">Нет (оптимально)</string>
|
||||
<string name="center_none_direct">Нет (напрямую)</string>
|
||||
<string name="settle_who">Кто платит</string>
|
||||
<string name="settle_to_whom">Кому</string>
|
||||
<string name="settle_how_much">Сумма</string>
|
||||
|
||||
@@ -247,6 +247,7 @@
|
||||
|
||||
<!-- Settlement -->
|
||||
<string name="center_none">None (Optimal)</string>
|
||||
<string name="center_none_direct">None (Direct)</string>
|
||||
<string name="settle_who">Who pays</string>
|
||||
<string name="settle_to_whom">To whom</string>
|
||||
<string name="settle_how_much">Amount</string>
|
||||
|
||||
Reference in New Issue
Block a user