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 }