This commit is contained in:
Rafal Wisniewski
2026-04-08 13:31:38 +02:00
parent 767d54e8f6
commit 3847e311a5
11 changed files with 308 additions and 85 deletions

View File

@@ -6,55 +6,93 @@ import androidx.room.Delete
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Upsert
import cc.n0th1ng.tripmoney.data.dto.SummaryPerCategoryRaw
import cc.n0th1ng.tripmoney.data.entity.Category
import cc.n0th1ng.tripmoney.data.entity.Expense
import cc.n0th1ng.tripmoney.data.entity.ExpenseDto
import kotlinx.coroutines.flow.Flow
@Dao
interface ExpenseDao {
@Upsert
suspend fun insert(expense: Expense)
@Query(
"""
SELECT expense.*, category.*
FROM expense
JOIN category ON expense.category_id = category.id
WHERE expense.trip_id = :tripId
AND
(
(:filter IS NULL OR category.name LIKE '%' || :filter || '%')
OR (:filter IS NULL OR expense.note LIKE '%' || :filter || '%')
SELECT * FROM expense
JOIN category ON expense.category_id = category.id
WHERE trip_id = :tripId
AND (
:search IS NULL
OR category.name LIKE '%' || :search || '%'
OR expense.note LIKE '%' || :search || '%'
)
ORDER BY expense.datetime DESC
AND (
:categoriesEmpty = 1
OR expense.category_id IN (:categoryIds)
)
AND (
:startAmount IS NULL OR expense.amount >= :startAmount
)
AND (
:endAmount IS NULL OR expense.amount <= :endAmount
)
ORDER BY expense.datetime DESC
"""
)
fun expenseDtoPaged(tripId: Int, filter: String): PagingSource<Int, ExpenseDto>
fun expenseDtoPaged(
tripId: Int,
search: String?,
categoryIds: List<Int>,
categoriesEmpty: Boolean,
startAmount: Double?,
endAmount: Double?
): PagingSource<Int, ExpenseDto>
@Transaction
@Query(
"""
SELECT * FROM expense
JOIN category ON expense.category_id = category.id
WHERE trip_id = :tripId
AND
(
(:filter IS NULL OR category.name LIKE '%' || :filter || '%')
OR (:filter IS NULL OR expense.note LIKE '%' || :filter || '%')
"""
SELECT * FROM expense
JOIN category ON expense.category_id = category.id
WHERE trip_id = :tripId
AND (
:search IS NULL
OR category.name LIKE '%' || :search || '%'
OR expense.note LIKE '%' || :search || '%'
)
AND (
:categoriesEmpty = 1
OR expense.category_id IN (:categoryIds)
)
AND (
:startAmount IS NULL OR expense.amount >= :startAmount
)
AND (
:endAmount IS NULL OR expense.amount <= :endAmount
)
ORDER BY expense.datetime DESC
"""
)
fun expenseDto(tripId: Int, filter: String): Flow<List<ExpenseDto>>
@Query("""
ORDER BY expense.datetime DESC
"""
)
fun expenseDto(
tripId: Int,
search: String?,
categoryIds: List<Int>,
categoriesEmpty: Boolean,
startAmount: Double?,
endAmount: Double?
): Flow<List<ExpenseDto>>
@Query(
"""
SELECT trip.budget - IFNULL(SUM(expense.amount * expense.rate), 0)
FROM trip
LEFT JOIN expense ON expense.trip_id = trip.id
WHERE trip.id = :tripId
""")
"""
)
fun budgetLeft(tripId: Int): Double
@Delete

View File

@@ -3,21 +3,16 @@ package cc.n0th1ng.tripmoney.data.repository
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.annotation.WorkerThread
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import cc.n0th1ng.tripmoney.Filter
import cc.n0th1ng.tripmoney.data.dao.ExpenseDao
import cc.n0th1ng.tripmoney.data.dto.SummaryPerCategoryRaw
import cc.n0th1ng.tripmoney.data.entity.Expense
import cc.n0th1ng.tripmoney.data.entity.ExpenseDto
import cc.n0th1ng.tripmoney.utils.Currencies
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import javax.inject.Inject
class ExpenseRepository @Inject constructor(
@@ -39,15 +34,43 @@ class ExpenseRepository @Inject constructor(
expenseDao.delete(expense)
}
fun getExpensesDtoPaged(tripId: Int, filter: String): Flow<PagingData<ExpenseDto>> {
fun getExpensesDtoPaged(
tripId: Int,
search: String,
filter: Filter,
): Flow<PagingData<ExpenseDto>> {
return Pager(
config = PagingConfig(pageSize = 50, enablePlaceholders = false),
pagingSourceFactory = { expenseDao.expenseDtoPaged(tripId, filter) }
pagingSourceFactory = {
val categoryIds = filter.categories.map { it.id }
expenseDao.expenseDtoPaged(
tripId = tripId,
search = search.takeIf { it.isNotBlank() },
categoryIds = categoryIds,
categoriesEmpty = categoryIds.isEmpty(),
startAmount = filter.startAmount,
endAmount = filter.endAmount
)
}
).flow
}
fun getExpensesDto(tripId: Int, filter: String = ""): Flow<List<ExpenseDto>> {
return expenseDao.expenseDto(tripId, filter)
fun getExpensesDto(
tripId: Int,
search: String = "",
filter: Filter = Filter()
): Flow<List<ExpenseDto>> {
val categoryIds = filter.categories.map { it.id }
return expenseDao.expenseDto(
tripId = tripId,
search = search.takeIf { it.isNotBlank() },
categoryIds = categoryIds,
categoriesEmpty = categoryIds.isEmpty(),
startAmount = filter.startAmount,
endAmount = filter.endAmount
)
}
@RequiresApi(Build.VERSION_CODES.O)