diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt index c329725..71e1b47 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt @@ -24,7 +24,8 @@ import com.mob.utsmyanmar.ui.sign_on.SignOnResultScreen import com.mob.utsmyanmar.ui.sign_on.SignOnRoute import com.mob.utsmyanmar.ui.sending_to_host.SendingToHostRoute import com.mob.utsmyanmar.ui.transaction_result.TransactionResultRoute -import com.mob.utsmyanmar.ui.void_trace.VoidTraceScreen +import com.mob.utsmyanmar.ui.sale_void.VoidViewModel +import com.mob.utsmyanmar.ui.sale_void.VoidTraceScreen import com.mob.utsmyanmar.viewmodel.CardReaderViewModel import com.mob.utsmyanmar.viewmodel.EmvTransactionProcessViewModel import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel @@ -83,10 +84,10 @@ fun AppNavGraph( } composable(Routes.VoidTrace.route) { - val sharedViewModel: SharedViewModel = hiltViewModel(activity) + val voidViewModel: VoidViewModel = hiltViewModel() VoidTraceScreen( - sharedViewModel = sharedViewModel, + voidViewModel = voidViewModel, onBack = { navController.popBackStack() } ) } @@ -259,7 +260,10 @@ fun AppNavGraph( } composable(Routes.SendingToHost.route) { + val sharedViewModel: SharedViewModel = hiltViewModel(activity) + SendingToHostRoute( + sharedViewModel = sharedViewModel, onNavigateTransactionResult = { navController.navigate(Routes.TransactionResult.route) { popUpTo(Routes.SendingToHost.route) { diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadViewModel.kt index d76d71f..af919d5 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/pinpad/PinPadViewModel.kt @@ -83,6 +83,7 @@ class PinPadViewModel @Inject constructor( MutableStateFlow(null) val pinStatus = _pinStatus.asStateFlow() + private var isTerminalStateReached = false /* * Trade Data @@ -121,6 +122,7 @@ class PinPadViewModel @Inject constructor( _alertMsg.value = null _errorCode.value = null _pinStatus.value = null + isTerminalStateReached = false } /* @@ -178,8 +180,10 @@ class PinPadViewModel @Inject constructor( fun cancelPinPad() { try { - mPinPadOptV2?.cancelInputPin() - Log.d(TAG, "PinPad Canceled") + if (!isTerminalStateReached) { + mPinPadOptV2?.cancelInputPin() + Log.d(TAG, "PinPad Canceled") + } } catch (e: RemoteException) { throw RuntimeException(e) } @@ -401,17 +405,21 @@ class PinPadViewModel @Inject constructor( ON_CONFIRM_CLICK -> { LogUtil.d(TAG, "ON CLICK CONFIRM") + isTerminalStateReached = true _pinStatus.value = PinPadStatus.ON_CONFIRM } ON_CANCEL_CLICK -> { LogUtil.d(TAG, "ON CLICK CANCEL") - _pinStatus.value = PinPadStatus.ON_CANCEL + if (!isTerminalStateReached) { + _pinStatus.value = PinPadStatus.ON_CANCEL + } } ON_ERROR_PIN_PAD -> { LogUtil.d(TAG, "ON ERROR CODE: ${msg.arg1}") _errorCode.value = msg.arg1 + isTerminalStateReached = true _pinStatus.value = PinPadStatus.ON_ERROR } @@ -420,11 +428,13 @@ class PinPadViewModel @Inject constructor( } ON_TIMEOUT_PIN_PAD -> { + isTerminalStateReached = true _pinStatus.value = PinPadStatus.ON_TIMEOUT } ON_ERROR_DUKPT -> { _alertMsg.value = "Try Again!" + isTerminalStateReached = true _pinStatus.value = PinPadStatus.ON_ERROR_DUKPT } } @@ -466,6 +476,7 @@ class PinPadViewModel @Inject constructor( payDetail?.cardType == -9 if (!isCardValid) { + isTerminalStateReached = true _pinStatus.value = PinPadStatus.ON_CARD_REMOVED return } @@ -481,6 +492,7 @@ class PinPadViewModel @Inject constructor( transType.value == TransactionsType.PRE_AUTH_VOID || transType.value == TransactionsType.REFUND ) { + isTerminalStateReached = true _pinStatus.value = PinPadStatus.ON_NEXT_SCREEN } else { handler.obtainMessage( @@ -490,9 +502,11 @@ class PinPadViewModel @Inject constructor( } override fun onCancel() { - handler.obtainMessage( - ON_CANCEL_CLICK - ).sendToTarget() + if (!isTerminalStateReached) { + handler.obtainMessage( + ON_CANCEL_CLICK + ).sendToTarget() + } } override fun onError(code: Int) { diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/void_trace/VoidTraceScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/sale_void/VoidTraceScreen.kt similarity index 96% rename from app/src/main/java/com/mob/utsmyanmar/ui/void_trace/VoidTraceScreen.kt rename to app/src/main/java/com/mob/utsmyanmar/ui/sale_void/VoidTraceScreen.kt index 07e1e1c..c99e423 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/void_trace/VoidTraceScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/sale_void/VoidTraceScreen.kt @@ -1,4 +1,4 @@ -package com.mob.utsmyanmar.ui.void_trace +package com.mob.utsmyanmar.ui.sale_void import android.util.Log import androidx.compose.foundation.background @@ -40,26 +40,29 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.mob.utsmyanmar.ui.components.appbar.AppBar import com.mob.utsmyanmar.ui.theme.Color -import com.mob.utsmyanmar.viewmodel.SharedViewModel import com.utsmyanmar.paylibs.model.PayDetail import com.utsmyanmar.paylibs.utils.POSUtil import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType @Composable fun VoidTraceScreen( - sharedViewModel: SharedViewModel, + voidViewModel: VoidViewModel, onBack: () -> Unit = {} ) { val tag = "VoidTraceScreen" var traceNumber by remember { mutableStateOf("") } var searchedTrace by remember { mutableStateOf("") } - val recentTransactions by sharedViewModel.getLastThreeTransactions().observeAsState(emptyList()) + val recentTransactions by voidViewModel.getLastThreeTransactions().observeAsState(emptyList()) val transactionSource: LiveData = remember(searchedTrace) { if (searchedTrace.isBlank()) { - MutableLiveData(null) + MutableLiveData(null) } else { - MutableLiveData(null) + @Suppress("UNCHECKED_CAST") + voidViewModel.getVoidTrans( + TransactionsType.SALE.value, + searchedTrace + ) as LiveData } } val transaction by transactionSource.observeAsState() @@ -74,8 +77,9 @@ fun VoidTraceScreen( } else { Color.Black } + - LaunchedEffect(recentTransactions) { + LaunchedEffect(searchedTrace, transaction) { Log.d( tag, "Recent DB traces: ${ @@ -84,15 +88,13 @@ fun VoidTraceScreen( } }" ) - } - - LaunchedEffect(searchedTrace, transaction) { if (searchedTrace.isNotBlank()) { Log.d( tag, "Search trace=$searchedTrace result=${transaction?.voucherNo ?: "NOT_FOUND"}" ) } + } Scaffold( diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/sale_void/VoidViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/sale_void/VoidViewModel.kt new file mode 100644 index 0000000..4419cb8 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/sale_void/VoidViewModel.kt @@ -0,0 +1,53 @@ +package com.mob.utsmyanmar.ui.sale_void + +import androidx.lifecycle.LiveData +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModel +import com.utsmyanmar.baselib.repo.Repository +import com.utsmyanmar.paylibs.model.PayDetail +import com.utsmyanmar.paylibs.system.SingleLiveEvent +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class VoidViewModel @Inject constructor( + private val repository: Repository +) : ViewModel() { + + val inputTrace = SingleLiveEvent() + val lists = SingleLiveEvent>() + + fun getVoidTransactions(transType: Int): LiveData> { + return repository.getVoidableTransactions(transType) + } + + fun getGenericVoidTransactions( + transType: Int, + voucherNo: String, + isEmv: Boolean + ): LiveData { + return repository.getGenericVoidTransaction(transType, voucherNo, isEmv) + } + + fun getVoidTrans(transType: Int, voucherNo: String): LiveData { + return repository.getVoidTransaction(transType, voucherNo) + } + + fun observeVoidTrans(transType: Int) { + getVoidTransactions(transType).observeForever(object : Observer> { + override fun onChanged(payDetails: List) { + if (lists.value == null) { + lists.postValue(payDetails) + } + } + }) + } + + fun searchTransaction(voucherNo: String): LiveData { + return repository.searchTransaction(voucherNo) + } + + fun getLastThreeTransactions(): LiveData> { + return repository.getLastThreeTransactions() + } +} diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/sending_to_host/SendingToHostRoute.kt b/app/src/main/java/com/mob/utsmyanmar/ui/sending_to_host/SendingToHostRoute.kt index e1e597e..b7b221e 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/sending_to_host/SendingToHostRoute.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/sending_to_host/SendingToHostRoute.kt @@ -2,15 +2,18 @@ package com.mob.utsmyanmar.ui.sending_to_host import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import com.mob.utsmyanmar.viewmodel.SharedViewModel import kotlinx.coroutines.delay private const val MOCK_HOST_DELAY_MS = 2000L @Composable fun SendingToHostRoute( + sharedViewModel: SharedViewModel, onNavigateTransactionResult: () -> Unit ) { LaunchedEffect(Unit) { + sharedViewModel.saveMockApprovedSaleForVoidTesting() delay(MOCK_HOST_DELAY_MS) onNavigateTransactionResult() } diff --git a/app/src/main/java/com/mob/utsmyanmar/viewmodel/SharedViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/viewmodel/SharedViewModel.kt index 8b5fc58..0dac340 100644 --- a/app/src/main/java/com/mob/utsmyanmar/viewmodel/SharedViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/viewmodel/SharedViewModel.kt @@ -14,10 +14,12 @@ import com.utsmyanmar.paylibs.model.PayDetail import com.utsmyanmar.paylibs.print.printx.PrintXReceipt import com.utsmyanmar.paylibs.print.printx.PrintXStatus import com.utsmyanmar.paylibs.system.SingleLiveEvent +import com.utsmyanmar.paylibs.system.SystemDateTime import com.utsmyanmar.paylibs.utils.AccountType import com.utsmyanmar.paylibs.utils.PrintStatus import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation import com.utsmyanmar.paylibs.utils.enums.HostType +import com.utsmyanmar.paylibs.utils.iso_utils.TransactionType import com.utsmyanmar.paylibs.utils.enums.TransMenu import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType import dagger.hilt.android.lifecycle.HiltViewModel @@ -441,6 +443,45 @@ class SharedViewModel @Inject constructor( repository.insertPayDetail(payDetail) } + fun saveMockApprovedSaleForVoidTesting() { + val detail = payDetail.value ?: return + + val systemParams = SystemParamsOperation.getInstance() + val mockTraceNo = systemParams.incrementSerialNum + val mockInvoiceNo = systemParams.incrementInvoiceNum + val mockApprovalCode = mockTraceNo.takeLast(6).padStart(6, '0') + val mockReferenceNo = buildString { + append(SystemDateTime.getYYMMDD()) + append(SystemDateTime.getHHmmss()) + }.takeLast(12) + + detail.voucherNo = mockTraceNo + detail.invoiceNo = mockInvoiceNo + detail.referNo = mockReferenceNo + detail.approvalCode = mockApprovalCode + detail.authNo = mockApprovalCode + detail.tradeAnswerCode = "00" + detail.tradeResultDes = "MOCK APPROVED" + detail.transactionType = TransactionType.SALE + detail.transType = TransactionsType.SALE.name + detail.isCanceled = false + detail.isSettle = false + detail.isNeedReversal = false + detail.isReturnGood = false + detail.TradeDate = SystemDateTime.getMMDD() + detail.TradeTime = SystemDateTime.getHHmmss() + detail.tradeDateAndTime = SystemDateTime.getMMDDhhmmss() + detail.tradeDateTime = SystemDateTime.getYYMMDDhhmmss() + detail.transDate = SystemDateTime.getTodayDateFormat() + detail.transTime = SystemDateTime.getTodayTimeFormat() + + repository.insertPayDetail(detail) + payDetail.value = detail + traceNo.value = mockTraceNo + rrNNo.value = mockReferenceNo + approvalCode.value = mockApprovalCode + } + fun enableCardStatusIcon( tapCard: Boolean, tapDevice: Boolean,