init
This commit is contained in:
@@ -1,35 +1,39 @@
|
||||
package cc.n0th1ng.tripmoney.viewmodel
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.cachedIn
|
||||
import androidx.paging.map
|
||||
import cc.n0th1ng.tripmoney.data.dto.SummaryPerCategory
|
||||
import cc.n0th1ng.tripmoney.data.entity.Category
|
||||
import cc.n0th1ng.tripmoney.data.entity.Expense
|
||||
import cc.n0th1ng.tripmoney.data.entity.ExpenseDto
|
||||
import cc.n0th1ng.tripmoney.data.repository.CategoryRepository
|
||||
import cc.n0th1ng.tripmoney.data.repository.ExchangeRateRepository
|
||||
import cc.n0th1ng.tripmoney.data.repository.ExpenseRepository
|
||||
import cc.n0th1ng.tripmoney.service.ExchangeService
|
||||
import cc.n0th1ng.tripmoney.data.repository.TripRepository
|
||||
import cc.n0th1ng.tripmoney.utils.Currencies
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import io.ktor.client.request.get
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.LocalDate
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.time.LocalDateTime
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ExpenseAndCategoryViewModel @Inject constructor(
|
||||
open class ExpenseAndCategoryViewModel @Inject constructor(
|
||||
private val expenseRepo: ExpenseRepository,
|
||||
private val categoryRepo: CategoryRepository,
|
||||
private val exchangeRateRepository: ExchangeRateRepository
|
||||
private val exchangeRateRepository: ExchangeRateRepository,
|
||||
private val tripRepo: TripRepository
|
||||
) : ViewModel() {
|
||||
|
||||
fun getExpenses(tripId: Int): Flow<PagingData<ExpenseDto>> =
|
||||
expenseRepo.getExpenses(tripId).cachedIn(viewModelScope)
|
||||
expenseRepo.getExpensesPaged(tripId).cachedIn(viewModelScope)
|
||||
|
||||
fun save(expense: Expense) {
|
||||
viewModelScope.launch {
|
||||
@@ -51,9 +55,81 @@ class ExpenseAndCategoryViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun convertAmount(amount: Double, base: Currencies, target: Currencies, date: LocalDate): Flow<Double> {
|
||||
return flow {
|
||||
emit(amount * exchangeRateRepository.getRate(base, target, date))
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
fun getSummaryPerCategory(tripId: Int): Flow<List<SummaryPerCategory>> {
|
||||
val tripCurrency = tripRepo.getTrip(tripId)?.currency ?: Currencies.default().name
|
||||
return getExpensesWithConvertedAmounts(tripId)
|
||||
.map { list ->
|
||||
// Compute summary
|
||||
val sumOfAll = list.sumOf { it.convertedAmount }
|
||||
list.groupBy { it.expenseDto.category }
|
||||
.map { (category, expenses) ->
|
||||
val total = expenses.sumOf { it.convertedAmount }
|
||||
SummaryPerCategory(
|
||||
category = category,
|
||||
amount = total,
|
||||
percent = (total / sumOfAll).toFloat(),
|
||||
currency = Currencies.valueOf(tripCurrency)
|
||||
)
|
||||
}.sortedBy { it.percent }.reversed()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
fun getExpensesWithConvertedAmounts(tripId: Int): Flow<List<ExpenseDtoWithConvertedAmount>> {
|
||||
return expenseRepo.getExpenses(tripId)
|
||||
.map { list ->
|
||||
list.map { expenseDto ->
|
||||
val convertedAmount =
|
||||
if (expenseDto.expense.currency != expenseDto.trip.currency) {
|
||||
runBlocking {
|
||||
expenseDto.toExpenseDtoWithConvertedAmount()
|
||||
}
|
||||
} else {
|
||||
expenseDto.expense.amount
|
||||
}
|
||||
ExpenseDtoWithConvertedAmount(expenseDto, convertedAmount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
fun getExpensesWithConvertedAmountsPaged(tripId: Int): Flow<PagingData<ExpenseDtoWithConvertedAmount>> {
|
||||
return expenseRepo.getExpensesPaged(tripId)
|
||||
.map { pagingData ->
|
||||
pagingData.map { expenseDto ->
|
||||
val convertedAmount =
|
||||
if (expenseDto.expense.currency != expenseDto.trip.currency) {
|
||||
runBlocking {
|
||||
expenseDto.toExpenseDtoWithConvertedAmount()
|
||||
}
|
||||
} else {
|
||||
expenseDto.expense.amount
|
||||
}
|
||||
ExpenseDtoWithConvertedAmount(expenseDto, convertedAmount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
fun clearOldRates() {
|
||||
viewModelScope.launch {
|
||||
exchangeRateRepository.clearOldRates()
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
suspend fun ExpenseDto.toExpenseDtoWithConvertedAmount(): Double {
|
||||
return exchangeRateRepository.getRate(
|
||||
Currencies.valueOf(this.expense.currency),
|
||||
Currencies.valueOf(this.trip.currency),
|
||||
LocalDateTime.parse(this.expense.datetime).toLocalDate()
|
||||
) * this.expense.amount
|
||||
}
|
||||
|
||||
data class ExpenseDtoWithConvertedAmount(
|
||||
val expenseDto: ExpenseDto,
|
||||
val convertedAmount: Double
|
||||
)
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import cc.n0th1ng.tripmoney.data.repository.AppTheme
|
||||
import cc.n0th1ng.tripmoney.data.repository.PreferencesRepository
|
||||
import cc.n0th1ng.tripmoney.utils.Currencies
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@@ -35,6 +36,17 @@ class SettingsViewModel @Inject constructor(
|
||||
-1
|
||||
)
|
||||
|
||||
val defaultCurrency = repo.defaultCurrencyFlow.stateIn(
|
||||
viewModelScope, SharingStarted.WhileSubscribed(5000),
|
||||
Currencies.default()
|
||||
)
|
||||
|
||||
fun setDefaultCurrency(currency: Currencies) {
|
||||
viewModelScope.launch {
|
||||
repo.saveDefaultCurrency(currency)
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurrentTrip(tripId: Int) {
|
||||
viewModelScope.launch {
|
||||
repo.saveCurrentTrip(tripId)
|
||||
|
||||
@@ -18,6 +18,8 @@ class TripViewModel @Inject constructor(private val repository: TripRepository)
|
||||
|
||||
fun getTrips(): Flow<PagingData<Trip>> = repository.getTrips().cachedIn(viewModelScope)
|
||||
|
||||
fun getTrip(tripId: Int): Trip? = repository.getTrip(tripId)
|
||||
|
||||
fun delete(trip: Trip) {
|
||||
viewModelScope.launch {
|
||||
repository.delete(trip)
|
||||
|
||||
Reference in New Issue
Block a user