Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class GoodsScannerViewModel @AssistedInject constructor(
- @Assisted private val orderId: String,
- private val router: Router,
- private val orderInteractor: OrderInteractor
- ) : BaseViewModel() {
- private val viewState = MutableLiveData<ViewState>().apply {
- value = ViewState(
- mode = ADD_MODE,
- totalGoodsQty = 0,
- positions = mutableListOf()
- )
- }
- private val coroutineScope = ViewModelCoroutineScope.create(this)
- private val verificationResultEvents = SingleLiveEvent<BarcodeVerificationResult>()
- private val barcodeSubject = PublishSubject.create<String>()
- private var barcodesDisposable: Disposable = Disposables.empty()
- @Volatile
- private var skipBarcodes = false
- private lateinit var session: GiveOrderSession
- init {
- loadViewState()
- }
- private fun loadViewState() = coroutineScope.launch {
- session = orderInteractor.getGiveOrderSession(orderId) ?: return@launch
- val positions = session.order.goodsForDelivery.map {
- PositionState(
- id = it.id,
- name = it.name,
- totalQty = it.shippedQuantity
- )
- }
- viewState.postUpdateValue { viewState ->
- viewState.copy(
- totalGoodsQty = positions.sumBy { it.totalQty },
- positions = positions
- )
- }
- barcodesDisposable = subscribeToBarcodes()
- }
- private fun subscribeToBarcodes() = barcodeSubject
- .skipWhile { skipBarcodes }
- .throttleLast(800L, TimeUnit.MILLISECONDS)
- .timestamp()
- .distinctUntilChanged { t1, t2 ->
- val sameValue = t1.value() == t2.value()
- val dropSameValue = t2.time() - t1.time() < 2000L
- Timber.d("sameValue=$sameValue, dropSameValue=$dropSameValue")
- sameValue && dropSameValue
- }
- .doOnNext { Timber.d("Barcode: $it") }
- .map { verifyBarcode(it.value()) }
- .observeOn(mainThread())
- .subscribeBy { result ->
- verificationResultEvents.value = result
- viewState.mutateValue { state ->
- updateViewState(state, result)
- }
- }
- private fun verifyBarcode(barcode: String): BarcodeVerificationResult {
- val product = session.findProductByBarcode(barcode)
- ?: return BarcodeVerificationResult.UnknownBarcode(barcode)
- return if (viewState.requireValue().mode == ADD_MODE) {
- mapToVerificationResult(session.addProduct(product.id), product)
- } else {
- mapToVerificationResult(session.removeProduct(product.id), product)
- }
- }
- private fun mapToVerificationResult(
- changeResult: ChangeResult,
- product: Product
- ): BarcodeVerificationResult =
- when (changeResult) {
- is ChangeResult.Added -> {
- BarcodeVerificationResult.PositionAdded(
- productId = product.id,
- productName = product.name,
- scannedQty = changeResult.newQty
- )
- }
- is ChangeResult.Removed -> {
- BarcodeVerificationResult.PositionRemoved(
- productId = product.id,
- productName = product.name,
- scannedQty = changeResult.newQty
- )
- }
- is ChangeResult.LimitExceeded -> {
- BarcodeVerificationResult.CanNotAddMore(productName = product.name)
- }
- is ChangeResult.NoProduct -> {
- BarcodeVerificationResult.CanNotRemove(productName = product.name)
- }
- }
- private fun updateViewState(viewState: ViewState, result: BarcodeVerificationResult) {
- when (result) {
- is BarcodeVerificationResult.PositionAdded -> {
- viewState.updatePositionQty(result.productId, result.scannedQty)
- }
- is BarcodeVerificationResult.PositionRemoved -> {
- viewState.updatePositionQty(result.productId, result.scannedQty)
- }
- }
- }
- fun switchToRemoveScanMode() {
- viewState.mutateValue {
- it.mode = REMOVE_MODE
- }
- }
- fun switchToAddScanMode() {
- viewState.mutateValue {
- it.mode = ADD_MODE
- }
- }
- fun addPosition(barcode: String) {
- val result = session.findProductByBarcode(barcode)?.let {
- mapToVerificationResult(session.addProduct(it.id), it)
- } ?: BarcodeVerificationResult.UnknownBarcode(barcode)
- verificationResultEvents.value = result
- viewState.mutateValue { state ->
- updateViewState(state, result)
- }
- }
- fun removePosition(barcode: String) {
- val result = session.findProductByBarcode(barcode)?.let {
- mapToVerificationResult(session.removeProduct(it.id), it)
- } ?: BarcodeVerificationResult.UnknownBarcode(barcode)
- verificationResultEvents.value = result
- viewState.mutateValue { state ->
- updateViewState(state, result)
- }
- }
- fun applyBarcode(barcode: String) {
- barcodeSubject.onNext(barcode)
- }
- fun pauseBarcodeVerification() {
- skipBarcodes = true
- }
- fun resumeBarcodeVerification() {
- skipBarcodes = false
- }
- fun getViewState(): LiveData<ViewState> = viewState
- fun getVerificationEvents(): SingleLiveEvent<BarcodeVerificationResult> =
- verificationResultEvents
- fun goBack() {
- router.exit()
- }
- override fun onCleared() {
- barcodesDisposable.dispose()
- coroutineScope.cancel()
- super.onCleared()
- }
- data class ViewState(
- @ScanMode var mode: Int,
- val totalGoodsQty: Int,
- val positions: List<PositionState> = mutableListOf()
- ) {
- var scannedGoodsQty: Int = 0
- private set
- fun updatePositionQty(productId: String, qty: Int) {
- positions.find { it.id == productId }?.scannedQty = qty
- scannedGoodsQty = positions.sumBy { it.scannedQty }
- }
- @IntDef(value = [ADD_MODE, REMOVE_MODE])
- annotation class ScanMode
- }
- sealed class BarcodeVerificationResult {
- class PositionAdded(
- val productId: String,
- val productName: String,
- val scannedQty: Int
- ) : BarcodeVerificationResult()
- class PositionRemoved(
- val productId: String,
- val productName: String,
- val scannedQty: Int
- ) : BarcodeVerificationResult()
- class CanNotAddMore(
- val productName: String
- ) : BarcodeVerificationResult()
- class CanNotRemove(
- val productName: String
- ) : BarcodeVerificationResult()
- class UnknownBarcode(
- val barcode: String
- ) : BarcodeVerificationResult()
- }
- @AssistedInject.Factory
- interface Factory {
- fun create(orderId: String): GoodsScannerViewModel
- }
- companion object {
- const val ADD_MODE = 0
- const val REMOVE_MODE = 1
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement