fix(#2): address PR review — use row mapper, require id==0, drop ignoreCase on amount, doc drift, orphan-category note
This commit is contained in:
@@ -17,6 +17,9 @@ class GetExpenseSummary(
|
||||
)
|
||||
val totalAmount = expenses.sumOf { it.amount }
|
||||
val categoryMap = categoryDao.getAll().associate { it.id to it.toModel() }
|
||||
// ForeignKey.RESTRICT keeps categories intact, but be defensive: if a
|
||||
// category was deleted out-of-band, drop its group from byCategory
|
||||
// rather than crashing. totalAmount still includes the orphan rows.
|
||||
val byCategory = expenses
|
||||
.groupBy { it.categoryId }
|
||||
.mapNotNull { (categoryId, group) ->
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.achmad.ledgerr.domain.expense.interactor
|
||||
|
||||
import dev.achmad.ledgerr.data.local.dao.CategoryDao
|
||||
import dev.achmad.ledgerr.data.local.dao.ExpenseDao
|
||||
import dev.achmad.ledgerr.data.local.dao.ExpenseWithCategoryRow
|
||||
import dev.achmad.ledgerr.data.local.mapper.toModel
|
||||
import dev.achmad.ledgerr.domain.expense.model.DateRange
|
||||
import dev.achmad.ledgerr.domain.expense.model.ExpenseWithCategory
|
||||
@@ -24,10 +25,10 @@ class GetExpenses(
|
||||
suspend fun awaitOne(id: Long): ExpenseWithCategory? {
|
||||
val expense = dao.getById(id) ?: return null
|
||||
val category = categoryDao.getById(expense.categoryId) ?: return null
|
||||
return ExpenseWithCategory(
|
||||
expense = expense.toModel(),
|
||||
category = category.toModel(),
|
||||
)
|
||||
return ExpenseWithCategoryRow(
|
||||
expense = expense,
|
||||
category = category,
|
||||
).toModel()
|
||||
}
|
||||
|
||||
suspend fun awaitAll(
|
||||
@@ -46,7 +47,7 @@ class GetExpenses(
|
||||
val amountStr = entity.amount.toString()
|
||||
val categoryName = categoryMap[entity.categoryId]?.name.orEmpty()
|
||||
note.contains(query, ignoreCase = true) ||
|
||||
amountStr.contains(query, ignoreCase = true) ||
|
||||
amountStr.contains(query) ||
|
||||
categoryName.contains(query, ignoreCase = true)
|
||||
}
|
||||
.mapNotNull { entity ->
|
||||
|
||||
@@ -9,6 +9,9 @@ class InsertExpenses(
|
||||
) {
|
||||
suspend fun awaitAll(expenses: List<Expense>) {
|
||||
if (expenses.isEmpty()) return
|
||||
require(expenses.all { it.id == 0L }) {
|
||||
"InsertExpenses.awaitAll requires all Expense.id == 0L (got ${expenses.filter { it.id != 0L }.map { it.id }})"
|
||||
}
|
||||
dao.insertAll(expenses.map { it.toEntity() })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ One-shot search. If `query` is blank and `range` is null, returns all expenses (
|
||||
## expense / UpsertExpense
|
||||
|
||||
### `await(expense: Expense): Long`
|
||||
If `expense.id == 0L`: insert and return generated id. Otherwise: update by id and return the existing id. Uses Room `@Upsert`.
|
||||
If `expense.id == 0L`: insert and return generated id. Otherwise: update by id and return the existing id. Routes through separate `dao.insert` / `dao.update` (the DAO does not expose a `@Upsert` method).
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user