diff options
author | Torsten Grote <t@grobox.de> | 2020-03-30 14:17:09 -0300 |
---|---|---|
committer | Torsten Grote <t@grobox.de> | 2020-03-30 14:17:09 -0300 |
commit | db0cf385fe707091f219cc61fb4e12b5b1fe64d0 (patch) | |
tree | c50aca48f996e0dec20315cde0ae4d278bdf0640 | |
parent | 1dbc22f1faba07331953d761097d5ad91ffff5ce (diff) | |
download | taler-android-db0cf385fe707091f219cc61fb4e12b5b1fe64d0.tar.gz taler-android-db0cf385fe707091f219cc61fb4e12b5b1fe64d0.tar.bz2 taler-android-db0cf385fe707091f219cc61fb4e12b5b1fe64d0.zip |
Fix amount serialization in PoS app
5 files changed, 47 insertions, 21 deletions
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/history/RefundFragment.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/history/RefundFragment.kt index 609eadd..7652ca4 100644 --- a/merchant-terminal/src/main/java/net/taler/merchantpos/history/RefundFragment.kt +++ b/merchant-terminal/src/main/java/net/taler/merchantpos/history/RefundFragment.kt @@ -28,6 +28,8 @@ import androidx.navigation.fragment.findNavController import com.google.android.material.snackbar.BaseTransientBottomBar.LENGTH_LONG import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.fragment_refund.* +import net.taler.common.Amount +import net.taler.common.AmountParserException import net.taler.common.fadeIn import net.taler.common.fadeOut import net.taler.common.navigate @@ -52,7 +54,7 @@ class RefundFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val item = refundManager.toBeRefunded ?: throw IllegalStateException() - amountInputView.setText(item.amount.toString()) + amountInputView.setText(item.amount.amountStr) currencyView.text = item.amount.currency abortButton.setOnClickListener { findNavController().navigateUp() } refundButton.setOnClickListener { onRefundButtonClicked(item) } @@ -63,12 +65,17 @@ class RefundFragment : Fragment() { } private fun onRefundButtonClicked(item: HistoryItem) { - val inputAmount = amountInputView.text.toString().toDouble() - if (inputAmount > item.amountStr.toDouble()) { // TODO real Amount comparision + val inputAmount = try { + Amount.fromString(item.amount.currency, amountInputView.text.toString()) + } catch (e: AmountParserException) { + amountView.error = getString(R.string.refund_error_invalid_amount) + return + } + if (inputAmount > item.amount) { amountView.error = getString(R.string.refund_error_max_amount, item.amountStr) return } - if (inputAmount <= 0.0) { + if (inputAmount.isZero()) { amountView.error = getString(R.string.refund_error_zero) return } diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/history/RefundManager.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/history/RefundManager.kt index 270b3b8..910116e 100644 --- a/merchant-terminal/src/main/java/net/taler/merchantpos/history/RefundManager.kt +++ b/merchant-terminal/src/main/java/net/taler/merchantpos/history/RefundManager.kt @@ -24,6 +24,7 @@ import com.android.volley.Request.Method.POST import com.android.volley.RequestQueue import com.android.volley.Response.ErrorListener import com.android.volley.Response.Listener +import net.taler.common.Amount import net.taler.merchantpos.config.ConfigManager import net.taler.merchantpos.config.MerchantRequest import org.json.JSONObject @@ -34,7 +35,7 @@ sealed class RefundResult { class Success( val refundUri: String, val item: HistoryItem, - val amount: Double, + val amount: Amount, val reason: String ) : RefundResult() } @@ -44,6 +45,10 @@ class RefundManager( private val queue: RequestQueue ) { + companion object { + val TAG = RefundManager::class.java.simpleName + } + var toBeRefunded: HistoryItem? = null private set @@ -57,14 +62,15 @@ class RefundManager( } @UiThread - internal fun refund(item: HistoryItem, amount: Double, reason: String) { + internal fun refund(item: HistoryItem, amount: Amount, reason: String) { val merchantConfig = configManager.merchantConfig!! val refundRequest = mapOf( "order_id" to item.orderId, - "refund" to "${item.amount.currency}:$amount", + "refund" to amount.toJSONString(), "reason" to reason ) val body = JSONObject(refundRequest) + Log.d(TAG, body.toString(4)) val req = MerchantRequest(POST, merchantConfig, "refund", null, body, Listener { onRefundResponse(it, item, amount, reason) }, ErrorListener { onRefundError() } @@ -76,7 +82,7 @@ class RefundManager( private fun onRefundResponse( json: JSONObject, item: HistoryItem, - amount: Double, + amount: Amount, reason: String ) { if (!json.has("contract_terms")) { diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt index f83370e..054d7cd 100644 --- a/merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt +++ b/merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt @@ -71,9 +71,9 @@ class PaymentManager( val merchantConfig = configManager.merchantConfig!! val currency = merchantConfig.currency!! - val amount = order.total.toJSONString() val summary = order.summary val summaryI18n = order.summaryI18n +// val refundDeadline = Timestamp(System.currentTimeMillis() + HOURS.toMillis(2)) mPayment.value = Payment(order, summary, currency) @@ -82,12 +82,13 @@ class PaymentManager( "${FULFILLMENT_PREFIX}${URLEncoder.encode(summary, "UTF-8")}#$fulfillmentId" val body = JSONObject().apply { put("order", JSONObject().apply { - put("amount", amount) + put("amount", order.total.toJSONString()) put("summary", summary) if (summaryI18n != null) put("summary_i18n", order.summaryI18n) // fulfillment_url needs to be unique per order put("fulfillment_url", fulfillmentUrl) put("instance", "default") +// put("refund_deadline", JSONObject(mapper.writeValueAsString(refundDeadline))) put("products", order.getProductsJson()) }) } diff --git a/merchant-terminal/src/main/res/values/strings.xml b/merchant-terminal/src/main/res/values/strings.xml index 863ae6f..756ef38 100644 --- a/merchant-terminal/src/main/res/values/strings.xml +++ b/merchant-terminal/src/main/res/values/strings.xml @@ -53,6 +53,7 @@ <string name="refund_abort">Abort</string> <string name="refund_confirm">Give Refund</string> <string name="refund_error_max_amount">Greater than order amount of %s</string> + <string name="refund_error_invalid_amount">Invalid amount</string> <string name="refund_error_zero">Needs to be positive amount</string> <string name="refund_error_backend">Error processing refund</string> <string name="refund_error_deadline">Refund deadline has passed</string> 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 49b699f..bd12a40 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 @@ -17,30 +17,24 @@ package net.taler.common import android.annotation.SuppressLint +import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonMappingException +import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import com.fasterxml.jackson.databind.ser.std.StdSerializer import org.json.JSONObject import java.lang.Math.floorDiv import kotlin.math.pow import kotlin.math.roundToInt -class AmountDeserializer : StdDeserializer<Amount>(Amount::class.java) { - override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Amount { - val node = p.codec.readValue(p, String::class.java) - try { - return Amount.fromJSONString(node) - } catch (e: AmountParserException) { - throw JsonMappingException(p, "Error parsing Amount", e) - } - } -} - class AmountParserException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) class AmountOverflowException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) +@JsonSerialize(using = AmountSerializer::class) @JsonDeserialize(using = AmountDeserializer::class) data class Amount( /** @@ -215,3 +209,20 @@ data class Amount( } } + +class AmountSerializer : StdSerializer<Amount>(Amount::class.java) { + override fun serialize(value: Amount, gen: JsonGenerator, provider: SerializerProvider) { + gen.writeString(value.toJSONString()) + } +} + +class AmountDeserializer : StdDeserializer<Amount>(Amount::class.java) { + override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Amount { + val node = p.codec.readValue(p, String::class.java) + try { + return Amount.fromJSONString(node) + } catch (e: AmountParserException) { + throw JsonMappingException(p, "Error parsing Amount", e) + } + } +} |