taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

LiveOrder.kt (4762B)


      1 /*
      2  * This file is part of GNU Taler
      3  * (C) 2020 Taler Systems S.A.
      4  *
      5  * GNU Taler is free software; you can redistribute it and/or modify it under the
      6  * terms of the GNU General Public License as published by the Free Software
      7  * Foundation; either version 3, or (at your option) any later version.
      8  *
      9  * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
     10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11  * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License along with
     14  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 
     17 package net.taler.merchantpos.order
     18 
     19 import androidx.annotation.UiThread
     20 import androidx.lifecycle.LiveData
     21 import androidx.lifecycle.MutableLiveData
     22 import androidx.lifecycle.map
     23 import net.taler.common.Amount
     24 import net.taler.common.CombinedLiveData
     25 import net.taler.common.CurrencySpecification
     26 import net.taler.merchantpos.config.Category
     27 import net.taler.merchantpos.config.ConfigProduct
     28 import net.taler.merchantpos.order.RestartState.DISABLED
     29 import net.taler.merchantpos.order.RestartState.ENABLED
     30 import net.taler.merchantpos.order.RestartState.UNDO
     31 
     32 internal enum class RestartState { ENABLED, DISABLED, UNDO }
     33 
     34 internal interface LiveOrder {
     35     val order: LiveData<Order?>
     36     val orderTotal: LiveData<Amount>
     37     val restartState: LiveData<RestartState>
     38     val modifyOrderAllowed: LiveData<Boolean>
     39     val increaseOrderAllowed: LiveData<Boolean>
     40     val lastAddedProduct: ConfigProduct?
     41     val selectedProductKey: String?
     42     fun restartOrUndo()
     43     fun selectOrderLine(product: ConfigProduct?)
     44     fun increaseSelectedOrderLine()
     45     fun decreaseSelectedOrderLine()
     46 }
     47 
     48 internal class MutableLiveOrder(
     49     val id: Int,
     50     private val currency: String,
     51     private val currencySpec: CurrencySpecification?,
     52     private val productsByCategory: HashMap<Category, ArrayList<ConfigProduct>>,
     53     private val canAddProduct: (ConfigProduct) -> Boolean,
     54     private val onChanged: () -> Unit,
     55 ) : LiveOrder {
     56     private val availableCategories: Map<Int, Category>
     57         get() = productsByCategory.keys.map { it.id to it }.toMap()
     58     override val order: MutableLiveData<Order?> =
     59         MutableLiveData(Order(id, currency, currencySpec, availableCategories))
     60     override val orderTotal: LiveData<Amount> =
     61         order.map { it?.total ?: Amount.zero(currency).withSpec(currencySpec) }
     62     override val restartState = MutableLiveData(DISABLED)
     63     private val selectedOrderLine = MutableLiveData<ConfigProduct?>()
     64     override val selectedProductKey: String?
     65         get() = selectedOrderLine.value?.id
     66     override val modifyOrderAllowed =
     67         CombinedLiveData(restartState, selectedOrderLine) { restartState, selectedOrderLine ->
     68             restartState != DISABLED && selectedOrderLine != null
     69         }
     70     override val increaseOrderAllowed =
     71         CombinedLiveData(order, selectedOrderLine) { order, selectedOrderLine ->
     72             order != null && selectedOrderLine != null && canAddProduct(selectedOrderLine)
     73         }
     74     override var lastAddedProduct: ConfigProduct? = null
     75     private var undoOrder: Order? = null
     76 
     77     @UiThread
     78     internal fun addProduct(product: ConfigProduct) {
     79         if (!canAddProduct(product)) return
     80         lastAddedProduct = product
     81         order.value = order.value!! + product
     82         restartState.value = ENABLED
     83         onChanged()
     84     }
     85 
     86     @UiThread
     87     internal fun removeProduct(product: ConfigProduct) {
     88         val modifiedOrder = order.value!! - product
     89         order.value = modifiedOrder
     90         restartState.value = if (modifiedOrder.products.isEmpty()) DISABLED else ENABLED
     91         onChanged()
     92     }
     93 
     94     @UiThread
     95     internal fun isEmpty() = order.value!!.products.isEmpty()
     96 
     97     @UiThread
     98     override fun restartOrUndo() {
     99         if (restartState.value == UNDO) {
    100             order.value = undoOrder
    101             restartState.value = ENABLED
    102             undoOrder = null
    103         } else {
    104             undoOrder = order.value
    105             order.value = Order(id, currency, currencySpec, availableCategories)
    106             restartState.value = UNDO
    107         }
    108         onChanged()
    109     }
    110 
    111     @UiThread
    112     override fun selectOrderLine(product: ConfigProduct?) {
    113         selectedOrderLine.value = product
    114     }
    115 
    116     @UiThread
    117     override fun increaseSelectedOrderLine() {
    118         val orderLine = selectedOrderLine.value ?: throw IllegalStateException()
    119         addProduct(orderLine)
    120     }
    121 
    122     @UiThread
    123     override fun decreaseSelectedOrderLine() {
    124         val orderLine = selectedOrderLine.value ?: throw IllegalStateException()
    125         removeProduct(orderLine)
    126     }
    127 
    128 }