aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle2
-rw-r--r--cashier/src/main/java/net/taler/cashier/BalanceFragment.kt12
-rw-r--r--cashier/src/main/java/net/taler/cashier/HttpHelper.kt4
-rw-r--r--cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt2
-rw-r--r--cashier/src/main/java/net/taler/cashier/withdraw/WithdrawManager.kt24
-rw-r--r--cashier/src/main/res/layout-w550dp/fragment_balance.xml2
-rw-r--r--cashier/src/main/res/layout/fragment_balance.xml2
-rw-r--r--taler-kotlin-common/src/main/java/net/taler/common/Amount.kt27
-rw-r--r--taler-kotlin-common/src/test/java/net/taler/common/AmountTest.kt21
9 files changed, 69 insertions, 27 deletions
diff --git a/build.gradle b/build.gradle
index b1f47dd..57a780b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
buildscript {
- ext.kotlin_version = '1.3.70'
+ ext.kotlin_version = '1.3.71'
ext.nav_version = "2.2.1"
ext.build_tools_version = "29.0.2"
repositories {
diff --git a/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt b/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt
index fffb21b..c4802ee 100644
--- a/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt
+++ b/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt
@@ -33,6 +33,7 @@ import kotlinx.android.synthetic.main.fragment_balance.*
import net.taler.cashier.BalanceFragmentDirections.Companion.actionBalanceFragmentToTransactionFragment
import net.taler.cashier.withdraw.LastTransaction
import net.taler.cashier.withdraw.WithdrawStatus
+import net.taler.common.Amount
import net.taler.common.SignedAmount
import net.taler.common.fadeIn
import net.taler.common.fadeOut
@@ -142,14 +143,15 @@ class BalanceFragment : Fragment() {
amountView.error = null
}
- private fun getAmountFromView(): Int {
+ private fun getAmountFromView(): Amount {
val str = amountView.editText!!.text.toString()
- if (str.isBlank()) return 0
- return Integer.parseInt(str)
+ val currency = viewModel.currency.value!!
+ if (str.isBlank()) return Amount.zero(currency)
+ return Amount.fromString(currency, str)
}
- private fun onAmountConfirmed(amount: Int) {
- if (amount <= 0) {
+ private fun onAmountConfirmed(amount: Amount) {
+ if (amount.isZero()) {
amountView.error = getString(R.string.withdraw_error_zero)
} else if (!withdrawManager.hasSufficientBalance(amount)) {
amountView.error = getString(R.string.withdraw_error_insufficient_balance)
diff --git a/cashier/src/main/java/net/taler/cashier/HttpHelper.kt b/cashier/src/main/java/net/taler/cashier/HttpHelper.kt
index 06b06db..43ba4d8 100644
--- a/cashier/src/main/java/net/taler/cashier/HttpHelper.kt
+++ b/cashier/src/main/java/net/taler/cashier/HttpHelper.kt
@@ -57,11 +57,11 @@ object HttpHelper {
private val MEDIA_TYPE_JSON = MediaType.parse("$MIME_TYPE_JSON; charset=utf-8")
@WorkerThread
- fun makeJsonPostRequest(url: String, body: String, config: Config): HttpJsonResult {
+ fun makeJsonPostRequest(url: String, body: JSONObject, config: Config): HttpJsonResult {
val request = Request.Builder()
.addHeader("Accept", MIME_TYPE_JSON)
.url(url)
- .post(RequestBody.create(MEDIA_TYPE_JSON, body))
+ .post(RequestBody.create(MEDIA_TYPE_JSON, body.toString()))
.build()
val response = try {
getHttpClient(config.username, config.password)
diff --git a/cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt b/cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt
index 8857bfa..e433540 100644
--- a/cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt
+++ b/cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt
@@ -54,7 +54,7 @@ class TransactionFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
withdrawManager.withdrawAmount.observe(viewLifecycleOwner, Observer { amount ->
- amountView.text = amount
+ amountView.text = amount?.toString()
})
withdrawManager.withdrawResult.observe(viewLifecycleOwner, Observer { result ->
onWithdrawResultReceived(result)
diff --git a/cashier/src/main/java/net/taler/cashier/withdraw/WithdrawManager.kt b/cashier/src/main/java/net/taler/cashier/withdraw/WithdrawManager.kt
index 88df6b7..317d1bf 100644
--- a/cashier/src/main/java/net/taler/cashier/withdraw/WithdrawManager.kt
+++ b/cashier/src/main/java/net/taler/cashier/withdraw/WithdrawManager.kt
@@ -34,6 +34,7 @@ import net.taler.cashier.HttpJsonResult.Error
import net.taler.cashier.HttpJsonResult.Success
import net.taler.cashier.MainViewModel
import net.taler.cashier.R
+import net.taler.common.Amount
import net.taler.common.QrCodeManager.makeQrCode
import org.json.JSONObject
import java.util.concurrent.TimeUnit.MINUTES
@@ -59,8 +60,8 @@ class WithdrawManager(
private var withdrawStatusCheck: Job? = null
- private val mWithdrawAmount = MutableLiveData<String>()
- val withdrawAmount: LiveData<String> = mWithdrawAmount
+ private val mWithdrawAmount = MutableLiveData<Amount>()
+ val withdrawAmount: LiveData<Amount> = mWithdrawAmount
private val mWithdrawResult = MutableLiveData<WithdrawResult>()
val withdrawResult: LiveData<WithdrawResult> = mWithdrawResult
@@ -72,22 +73,23 @@ class WithdrawManager(
val lastTransaction: LiveData<LastTransaction> = mLastTransaction
@UiThread
- fun hasSufficientBalance(amount: Int): Boolean {
+ fun hasSufficientBalance(amount: Amount): Boolean {
val balanceResult = viewModel.balance.value
if (balanceResult !is BalanceResult.Success) return false
- return balanceResult.amount.positive && amount <= balanceResult.amount.amount.value
+ return balanceResult.amount.positive && amount <= balanceResult.amount.amount
}
@UiThread
- fun withdraw(amount: Int) {
- check(amount > 0) { "Withdraw amount was <= 0" }
+ fun withdraw(amount: Amount) {
+ check(!amount.isZero()) { "Withdraw amount was 0" }
check(currency != null) { "Currency is null" }
mWithdrawResult.value = null
- mWithdrawAmount.value = "$amount $currency"
+ mWithdrawAmount.value = amount
scope.launch(Dispatchers.IO) {
val url = "${config.bankUrl}/accounts/${config.username}/withdrawals"
Log.d(TAG, "Starting withdrawal at $url")
- val body = JSONObject(mapOf("amount" to "${currency}:${amount}")).toString()
+ val map = mapOf("amount" to amount.toJSONString())
+ val body = JSONObject(map)
when (val result = makeJsonPostRequest(url, body, config)) {
is Success -> {
val talerUri = result.json.getString("taler_withdraw_uri")
@@ -178,7 +180,7 @@ class WithdrawManager(
private fun abort(withdrawalId: String) = scope.launch(Dispatchers.IO) {
val url = "${config.bankUrl}/accounts/${config.username}/withdrawals/${withdrawalId}/abort"
Log.d(TAG, "Aborting withdrawal at $url")
- makeJsonPostRequest(url, "", config)
+ makeJsonPostRequest(url, JSONObject(), config)
}
@UiThread
@@ -188,7 +190,7 @@ class WithdrawManager(
val url =
"${config.bankUrl}/accounts/${config.username}/withdrawals/${withdrawalId}/confirm"
Log.d(TAG, "Confirming withdrawal at $url")
- when (val result = makeJsonPostRequest(url, "", config)) {
+ when (val result = makeJsonPostRequest(url, JSONObject(), config)) {
is Success -> {
// no-op still waiting for [timer] to confirm our confirmation
}
@@ -226,6 +228,6 @@ sealed class WithdrawStatus {
}
data class LastTransaction(
- val withdrawAmount: String,
+ val withdrawAmount: Amount,
val withdrawStatus: WithdrawStatus
)
diff --git a/cashier/src/main/res/layout-w550dp/fragment_balance.xml b/cashier/src/main/res/layout-w550dp/fragment_balance.xml
index d04698b..40fa6af 100644
--- a/cashier/src/main/res/layout-w550dp/fragment_balance.xml
+++ b/cashier/src/main/res/layout-w550dp/fragment_balance.xml
@@ -184,7 +184,7 @@
android:layout_height="wrap_content"
android:ems="6"
android:imeOptions="actionGo"
- android:inputType="number"
+ android:inputType="number|numberDecimal"
android:maxLength="4" />
</com.google.android.material.textfield.TextInputLayout>
diff --git a/cashier/src/main/res/layout/fragment_balance.xml b/cashier/src/main/res/layout/fragment_balance.xml
index 5dafc59..b50cfa9 100644
--- a/cashier/src/main/res/layout/fragment_balance.xml
+++ b/cashier/src/main/res/layout/fragment_balance.xml
@@ -185,7 +185,7 @@
android:layout_height="wrap_content"
android:ems="6"
android:imeOptions="actionGo"
- android:inputType="number"
+ android:inputType="number|numberDecimal"
android:maxLength="4" />
</com.google.android.material.textfield.TextInputLayout>
diff --git a/taler-kotlin-common/src/main/java/net/taler/common/Amount.kt b/taler-kotlin-common/src/main/java/net/taler/common/Amount.kt
index 48bd643..49b699f 100644
--- a/taler-kotlin-common/src/main/java/net/taler/common/Amount.kt
+++ b/taler-kotlin-common/src/main/java/net/taler/common/Amount.kt
@@ -64,7 +64,7 @@ data class Amount(
* of 50_000_000 would correspond to 50 cents.
*/
val fraction: Int
-) {
+) : Comparable<Amount> {
companion object {
@@ -88,10 +88,14 @@ data class Amount(
fun fromJSONString(str: String): Amount {
val split = str.split(":")
if (split.size != 2) throw AmountParserException("Invalid Amount Format")
- // currency
- val currency = checkCurrency(split[0])
+ return fromString(split[0], split[1])
+ }
+
+ @Throws(AmountParserException::class)
+ @SuppressLint("CheckedExceptions")
+ fun fromString(currency: String, str: String): Amount {
// value
- val valueSplit = split[1].split(".")
+ val valueSplit = str.split(".")
val value = checkValue(valueSplit[0].toLongOrNull())
// fraction
val fraction: Int = if (valueSplit.size > 1) {
@@ -103,7 +107,7 @@ data class Amount(
?.roundToInt()
checkFraction(fraction)
} else 0
- return Amount(currency, value, fraction)
+ return Amount(checkCurrency(currency), value, fraction)
}
@Throws(AmountParserException::class)
@@ -197,4 +201,17 @@ data class Amount(
return "$amountStr $currency"
}
+ override fun compareTo(other: Amount): Int {
+ check(currency == other.currency) { "Can only compare amounts with the same currency" }
+ when {
+ value == other.value -> {
+ if (fraction < other.fraction) return -1
+ if (fraction > other.fraction) return 1
+ return 0
+ }
+ value < other.value -> return -1
+ else -> return 1
+ }
+ }
+
}
diff --git a/taler-kotlin-common/src/test/java/net/taler/common/AmountTest.kt b/taler-kotlin-common/src/test/java/net/taler/common/AmountTest.kt
index c09da3c..97d9667 100644
--- a/taler-kotlin-common/src/test/java/net/taler/common/AmountTest.kt
+++ b/taler-kotlin-common/src/test/java/net/taler/common/AmountTest.kt
@@ -275,6 +275,27 @@ class AmountTest {
assertFalse(Amount.fromJSONString("EUR:0001.0").isZero())
}
+ @Test
+ fun `test comparision`() {
+ assertTrue(Amount.fromJSONString("EUR:0") <= Amount.fromJSONString("EUR:0"))
+ assertTrue(Amount.fromJSONString("EUR:0") <= Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0") < Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0") < Amount.fromJSONString("EUR:1"))
+ assertTrue(Amount.fromJSONString("EUR:0") == Amount.fromJSONString("EUR:0"))
+ assertTrue(Amount.fromJSONString("EUR:42") == Amount.fromJSONString("EUR:42"))
+ assertTrue(Amount.fromJSONString("EUR:42.00000001") == Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:42.00000001") >= Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:42.00000002") >= Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:42.00000002") > Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0.00000002") > Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0.00000001") > Amount.fromJSONString("EUR:0"))
+ assertTrue(Amount.fromJSONString("EUR:2") > Amount.fromJSONString("EUR:1"))
+
+ assertThrows<IllegalStateException>("could compare amounts with different currencies") {
+ Amount.fromJSONString("EUR:0.5") < Amount.fromJSONString("USD:0.50000001")
+ }
+ }
+
private inline fun <reified T : Throwable> assertThrows(
msg: String? = null,
function: () -> Any