gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant-terminal-android] 17/19: Make order sorting deterministi


From: gnunet
Subject: [taler-merchant-terminal-android] 17/19: Make order sorting deterministic
Date: Fri, 21 Feb 2020 19:00:10 +0100

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a commit to branch master
in repository merchant-terminal-android.

commit 2256d2fa3e6b9b25a1e90c4a690a4af3820d651e
Author: Torsten Grote <address@hidden>
AuthorDate: Thu Feb 20 16:55:29 2020 -0300

    Make order sorting deterministic
---
 .../net/taler/merchantpos/order/Definitions.kt     | 54 ++++++++++++++++------
 .../net/taler/merchantpos/order/OrderManager.kt    | 10 ++--
 .../taler/merchantpos/order/OrderStateFragment.kt  | 54 ++++++++++++++--------
 .../taler/merchantpos/payment/PaymentManager.kt    |  2 +-
 4 files changed, 81 insertions(+), 39 deletions(-)

diff --git a/app/src/main/java/net/taler/merchantpos/order/Definitions.kt 
b/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
index ce2e464..872f2f5 100644
--- a/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
@@ -1,5 +1,6 @@
 package net.taler.merchantpos.order
 
+import com.fasterxml.jackson.annotation.JsonIgnore
 import com.fasterxml.jackson.annotation.JsonProperty
 import net.taler.merchantpos.Amount
 
@@ -24,9 +25,24 @@ data class ConfigProduct(
     override val price: String,
     @JsonProperty("delivery_location")
     override val location: String?,
-    val categories: List<Int>
+    val categories: List<Int>,
+    @JsonIgnore
+    val quantity: Int = 0
 ) : Product {
     val priceAsDouble by lazy { Amount.fromString(price).amount.toDouble() }
+
+    override fun equals(other: Any?): Boolean {
+        return other is ConfigProduct && id == other.id
+    }
+
+    override fun hashCode(): Int {
+        var result = id.hashCode()
+        result = 31 * result + description.hashCode()
+        result = 31 * result + price.hashCode()
+        result = 31 * result + (location?.hashCode() ?: 0)
+        result = 31 * result + categories.hashCode()
+        return result
+    }
 }
 
 data class ContractProduct(
@@ -38,25 +54,25 @@ data class ContractProduct(
     override val location: String?,
     val quantity: Int
 ) : Product {
-    constructor(product: ConfigProduct, quantity: Int) : this(
+    constructor(product: ConfigProduct) : this(
         product.id,
         product.description,
         product.price,
         product.location,
-        quantity
+        product.quantity
     )
 }
 
 data class Order(val availableCategories: Map<Int, Category>) {
-    val products = HashMap<ConfigProduct, Int>()
+    val products = ArrayList<ConfigProduct>()
     val summary: String
         get() {
             val categories = HashMap<Category, Int>()
-            products.forEach { (product, quantity) ->
+            products.forEach { product ->
                 val categoryId = product.categories[0]
                 val category = availableCategories.getValue(categoryId)
                 val oldQuantity = categories[category] ?: 0
-                categories[category] = oldQuantity + quantity
+                categories[category] = oldQuantity + product.quantity
             }
             return categories.map { (category, quantity) ->
                 "$quantity x ${category.name}"
@@ -65,9 +81,9 @@ data class Order(val availableCategories: Map<Int, Category>) 
{
     val total: Double
         get() {
             var total = 0.0
-            products.forEach { (product, quantity) ->
+            products.forEach { product ->
                 val price = product.priceAsDouble
-                total += price * quantity
+                total += price * product.quantity
             }
             return total
         }
@@ -75,17 +91,25 @@ data class Order(val availableCategories: Map<Int, 
Category>) {
         get() = String.format("%.2f", total)
 
     operator fun plus(product: ConfigProduct): Order {
-        products[product] = (products[product] ?: 0) + 1
+        val i = products.indexOf(product)
+        if (i == -1) {
+            products.add(product.copy(quantity = 1))
+        } else {
+            val quantity = products[i].quantity
+            products[i] = products[i].copy(quantity = quantity + 1)
+        }
         return this
     }
 
     operator fun minus(product: ConfigProduct): Order {
-        var quantity = products[product] ?: throw IllegalStateException()
-        quantity -= 1
-        if (quantity > 0) products[product] = quantity
-        else products.remove(product)
+        val i = products.indexOf(product)
+        if (i == -1) return this
+        val quantity = products[i].quantity
+        if (quantity <= 1) {
+            products.remove(product)
+        } else {
+            products[i] = products[i].copy(quantity = quantity - 1)
+        }
         return this
     }
 }
-
-typealias OrderLine = Pair<ConfigProduct, Int>
diff --git a/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt 
b/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
index 449d741..1ff04d8 100644
--- a/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
@@ -41,7 +41,7 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
     private val mRestartState = MutableLiveData<RestartState>().apply { value 
= DISABLED }
     internal val restartState: LiveData<RestartState> = mRestartState
 
-    private val mSelectedOrderLine = MutableLiveData<OrderLine>()
+    private val mSelectedOrderLine = MutableLiveData<ConfigProduct>()
 
     internal val modifyOrderAllowed =
         CombinedLiveData(restartState, mSelectedOrderLine) { restartState, 
selectedOrderLine ->
@@ -134,20 +134,20 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
     }
 
     @UiThread
-    fun selectOrderLine(orderLine: OrderLine?) {
-        mSelectedOrderLine.value = orderLine
+    fun selectOrderLine(product: ConfigProduct?) {
+        mSelectedOrderLine.value = product
     }
 
     @UiThread
     fun increaseSelectedOrderLine() {
         val orderLine = mSelectedOrderLine.value ?: throw 
IllegalStateException()
-        addProduct(orderLine.first)
+        addProduct(orderLine)
     }
 
     @UiThread
     fun decreaseSelectedOrderLine() {
         val orderLine = mSelectedOrderLine.value ?: throw 
IllegalStateException()
-        removeProduct(orderLine.first)
+        removeProduct(orderLine)
     }
 
 }
diff --git 
a/app/src/main/java/net/taler/merchantpos/order/OrderStateFragment.kt 
b/app/src/main/java/net/taler/merchantpos/order/OrderStateFragment.kt
index 240ee3b..3988f17 100644
--- a/app/src/main/java/net/taler/merchantpos/order/OrderStateFragment.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/OrderStateFragment.kt
@@ -14,6 +14,8 @@ import androidx.recyclerview.selection.ItemKeyProvider
 import androidx.recyclerview.selection.SelectionPredicates
 import androidx.recyclerview.selection.SelectionTracker
 import androidx.recyclerview.selection.StorageStrategy
+import androidx.recyclerview.widget.AsyncListDiffer
+import androidx.recyclerview.widget.DiffUtil
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import androidx.recyclerview.widget.RecyclerView.Adapter
@@ -24,7 +26,6 @@ import net.taler.merchantpos.R
 import net.taler.merchantpos.order.OrderAdapter.OrderLineLookup
 import net.taler.merchantpos.order.OrderAdapter.OrderViewHolder
 
-
 class OrderStateFragment : Fragment() {
 
     private val viewModel: MainViewModel by activityViewModels()
@@ -67,7 +68,14 @@ class OrderStateFragment : Fragment() {
         this.tracker = tracker
 
         orderManager.order.observe(viewLifecycleOwner, Observer { order ->
-            adapter.setItems(order.products)
+            adapter.setItems(order.products) {
+                // workaround for bug: SelectionObserver doesn't update when 
removing selected item
+                if (tracker.hasSelection()) {
+                    val key = tracker.selection.first()
+                    val product = order.products.find { it.id == key }
+                    if (product == null) tracker.clearSelection()
+                }
+            }
         })
         orderManager.orderTotal.observe(viewLifecycleOwner, Observer { 
orderTotal ->
             if (orderTotal == 0.0) {
@@ -89,9 +97,18 @@ private class OrderAdapter : Adapter<OrderViewHolder>() {
 
     lateinit var tracker: SelectionTracker<String>
     val keyProvider = OrderKeyProvider()
-    private val orderLines = ArrayList<OrderLine>()
+    private val itemCallback = object : DiffUtil.ItemCallback<ConfigProduct>() 
{
+        override fun areItemsTheSame(oldItem: ConfigProduct, newItem: 
ConfigProduct): Boolean {
+            return oldItem == newItem
+        }
 
-    override fun getItemCount() = orderLines.size
+        override fun areContentsTheSame(oldItem: ConfigProduct, newItem: 
ConfigProduct): Boolean {
+            return oldItem.quantity == newItem.quantity
+        }
+    }
+    private val differ = AsyncListDiffer<ConfigProduct>(this, itemCallback)
+
+    override fun getItemCount() = differ.currentList.size
 
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
OrderViewHolder {
         val view =
@@ -100,18 +117,19 @@ private class OrderAdapter : Adapter<OrderViewHolder>() {
     }
 
     override fun onBindViewHolder(holder: OrderViewHolder, position: Int) {
-        val item = orderLines[position]
-        holder.bind(item, tracker.isSelected(item.first.id))
+        val item = getItem(position)!!
+        holder.bind(item, tracker.isSelected(item.id))
     }
 
-    fun setItems(items: HashMap<ConfigProduct, Int>) {
-        orderLines.clear()
-        items.forEach { t -> orderLines.add(t.toPair()) }
-        notifyDataSetChanged()
+    fun setItems(items: List<ConfigProduct>, commitCallback: () -> Unit) {
+        // toMutableList() is needed for some reason, otherwise doesn't update 
adapter
+        differ.submitList(items.toMutableList(), commitCallback)
     }
 
-    fun getItemByKey(key: String): OrderLine? {
-        return orderLines.find { it.first.id == key }
+    fun getItem(position: Int): ConfigProduct? = differ.currentList[position]
+
+    fun getItemByKey(key: String): ConfigProduct? {
+        return differ.currentList.find { it.id == key }
     }
 
     private inner class OrderViewHolder(private val v: View) : ViewHolder(v) {
@@ -119,18 +137,18 @@ private class OrderAdapter : Adapter<OrderViewHolder>() {
         private val name: TextView = v.findViewById(R.id.name)
         private val price: TextView = v.findViewById(R.id.price)
 
-        fun bind(orderLine: OrderLine, selected: Boolean) {
+        fun bind(product: ConfigProduct, selected: Boolean) {
             v.isActivated = selected
-            quantity.text = orderLine.second.toString()
-            name.text = orderLine.first.description
-            price.text = String.format("%.2f", orderLine.first.priceAsDouble * 
orderLine.second)
+            quantity.text = product.quantity.toString()
+            name.text = product.description
+            price.text = String.format("%.2f", product.priceAsDouble * 
product.quantity)
         }
     }
 
     private inner class OrderKeyProvider : 
ItemKeyProvider<String>(SCOPE_MAPPED) {
-        override fun getKey(position: Int) = orderLines[position].first.id
+        override fun getKey(position: Int) = getItem(position)!!.id
         override fun getPosition(key: String): Int {
-            return orderLines.indexOfFirst { it.first.id == key }
+            return differ.currentList.indexOfFirst { it.id == key }
         }
     }
 
diff --git a/app/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt 
b/app/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
index 30b417d..8167f86 100644
--- a/app/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
+++ b/app/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
@@ -79,7 +79,7 @@ class PaymentManager(
     }
 
     private fun Order.getProductsJson(): JSONArray {
-        val contractProducts = products.map { ContractProduct(it.key, 
it.value) }
+        val contractProducts = products.map { ContractProduct(it) }
         val productsStr = mapper.writeValueAsString(contractProducts)
         return JSONArray(productsStr)
     }

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]