diff options
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt')
-rw-r--r-- | wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt | 143 |
1 files changed, 109 insertions, 34 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt index fcc7787..d0dec41 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt @@ -23,13 +23,19 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.switchMap import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import net.taler.wallet.TAG +import net.taler.wallet.backend.TalerErrorInfo import net.taler.wallet.backend.WalletBackendApi -import net.taler.wallet.transactions.ExtendedStatus.Pending +import net.taler.wallet.balances.ScopeInfo +import net.taler.wallet.transactions.TransactionAction.Delete +import net.taler.wallet.transactions.TransactionMajorState.Pending +import org.json.JSONObject import java.util.LinkedList sealed class TransactionsResult { - class Error(val msg: String) : TransactionsResult() + class Error(val error: TalerErrorInfo) : TransactionsResult() class Success(val transactions: List<Transaction>) : TransactionsResult() } @@ -43,45 +49,40 @@ class TransactionManager( // FIXME if the app gets killed, this will not be restored and thus be unexpected null // we should keep this in a savable, maybe using Hilt and SavedStateViewModel - var selectedCurrency: String? = null + var selectedScope: ScopeInfo? = null val searchQuery = MutableLiveData<String>(null) private val mSelectedTransaction = MutableLiveData<Transaction?>(null) val selectedTransaction: LiveData<Transaction?> = mSelectedTransaction - private val allTransactions = HashMap<String, List<Transaction>>() - private val mTransactions = HashMap<String, MutableLiveData<TransactionsResult>>() + private val allTransactions = HashMap<ScopeInfo, List<Transaction>>() + private val mTransactions = HashMap<ScopeInfo, MutableLiveData<TransactionsResult>>() val transactions: LiveData<TransactionsResult> @UiThread get() = searchQuery.switchMap { query -> - val currency = selectedCurrency - check(currency != null) { "Did not select currency before getting transactions" } + val scopeInfo = selectedScope + check(scopeInfo != null) { "Did not select scope before getting transactions" } loadTransactions(query) - mTransactions[currency]!! // non-null because filled in [loadTransactions] + mTransactions[scopeInfo]!! // non-null because filled in [loadTransactions] } @UiThread fun loadTransactions(searchQuery: String? = null) = scope.launch { - val currency = selectedCurrency ?: return@launch - val liveData = mTransactions.getOrPut(currency) { MutableLiveData() } - if (searchQuery == null && allTransactions.containsKey(currency)) { - liveData.value = TransactionsResult.Success(allTransactions[currency]!!) + val scopeInfo = selectedScope ?: return@launch + val liveData = mTransactions.getOrPut(scopeInfo) { MutableLiveData() } + if (searchQuery == null && allTransactions.containsKey(scopeInfo)) { + liveData.value = TransactionsResult.Success(allTransactions[scopeInfo]!!) } if (liveData.value == null) mProgress.value = true api.request("getTransactions", Transactions.serializer()) { if (searchQuery != null) put("search", searchQuery) - put("currency", currency) + put("scopeInfo", JSONObject(Json.encodeToString(scopeInfo))) }.onError { - liveData.postValue(TransactionsResult.Error(it.userFacingMsg)) + liveData.postValue(TransactionsResult.Error(it)) mProgress.postValue(false) }.onSuccess { result -> val transactions = LinkedList(result.transactions) - // TODO remove when fixed in wallet-core - val comparator = compareBy<Transaction>( - { it.extendedStatus == Pending }, - { it.timestamp.ms }, - { it.transactionId } - ) + val comparator = compareBy<Transaction> { it.txState.major == Pending } transactions.sortWith(comparator) transactions.reverse() // show latest first @@ -96,8 +97,8 @@ class TransactionManager( mSelectedTransaction.value = it } - // update all transactions on UiThread if there was a currency - if (searchQuery == null) allTransactions[currency] = transactions + // update all transactions on UiThread if there was a scope info + if (searchQuery == null) allTransactions[scopeInfo] = transactions } } @@ -122,24 +123,98 @@ class TransactionManager( } } + suspend fun getTransactionById(transactionId: String): Transaction? { + var transaction: Transaction? = null + api.request("getTransactionById", Transaction.serializer()) { + put("transactionId", transactionId) + }.onError { + Log.e(TAG, "Error getting transaction $it") + }.onSuccess { result -> + transaction = result + } + return transaction + } + fun selectTransaction(transaction: Transaction) { mSelectedTransaction.postValue(transaction) } - fun deleteTransaction(transactionId: String) = scope.launch { - api.request<Unit>("deleteTransaction") { - put("transactionId", transactionId) - }.onError { - Log.e(TAG, "Error deleteTransaction $it") - }.onSuccess { - // re-load transactions as our list is stale otherwise - loadTransactions() + fun deleteTransaction(transactionId: String, onError: (it: TalerErrorInfo) -> Unit) = + scope.launch { + api.request<Unit>("deleteTransaction") { + put("transactionId", transactionId) + }.onError { + onError(it) + }.onSuccess { + // re-load transactions as our list is stale otherwise + loadTransactions() + } + } + + fun retryTransaction(transactionId: String, onError: (it: TalerErrorInfo) -> Unit) = + scope.launch { + api.request<Unit>("retryTransaction") { + put("transactionId", transactionId) + }.onError { + onError(it) + }.onSuccess { + loadTransactions() + } + } + + fun abortTransaction(transactionId: String, onError: (it: TalerErrorInfo) -> Unit) = + scope.launch { + api.request<Unit>("abortTransaction") { + put("transactionId", transactionId) + }.onError { + onError(it) + }.onSuccess { + loadTransactions() + } + } + + fun failTransaction(transactionId: String, onError: (it: TalerErrorInfo) -> Unit) = + scope.launch { + api.request<Unit>("failTransaction") { + put("transactionId", transactionId) + }.onError { + onError(it) + }.onSuccess { + loadTransactions() + } } - } - fun deleteTransactions(transactionIds: List<String>) { - transactionIds.forEach { id -> - deleteTransaction(id) + fun suspendTransaction(transactionId: String, onError: (it: TalerErrorInfo) -> Unit) = + scope.launch { + api.request<Unit>("suspendTransaction") { + put("transactionId", transactionId) + }.onError { + onError(it) + }.onSuccess { + loadTransactions() + } + } + + fun resumeTransaction(transactionId: String, onError: (it: TalerErrorInfo) -> Unit) = + scope.launch { + api.request<Unit>("resumeTransaction") { + put("transactionId", transactionId) + }.onError { + onError(it) + }.onSuccess { + loadTransactions() + } + } + + fun deleteTransactions(transactionIds: List<String>, onError: (it: TalerErrorInfo) -> Unit) { + allTransactions[selectedScope]?.filter { transaction -> + transaction.transactionId in transactionIds + }?.forEach { toBeDeletedTx -> + if (Delete in toBeDeletedTx.txActions) { + deleteTransaction(toBeDeletedTx.transactionId) { + onError(it) + } + } } } |