search void tran

This commit is contained in:
moon 2026-05-21 23:53:12 +06:30
parent dbc5424aab
commit 0f0bd49709
6 changed files with 136 additions and 19 deletions

View File

@ -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) {

View File

@ -83,6 +83,7 @@ class PinPadViewModel @Inject constructor(
MutableStateFlow<PinPadStatus?>(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) {

View File

@ -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<PayDetail?> = remember(searchedTrace) {
if (searchedTrace.isBlank()) {
MutableLiveData(null)
MutableLiveData<PayDetail?>(null)
} else {
MutableLiveData(null)
@Suppress("UNCHECKED_CAST")
voidViewModel.getVoidTrans(
TransactionsType.SALE.value,
searchedTrace
) as LiveData<PayDetail?>
}
}
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(

View File

@ -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<String>()
val lists = SingleLiveEvent<List<PayDetail>>()
fun getVoidTransactions(transType: Int): LiveData<List<PayDetail>> {
return repository.getVoidableTransactions(transType)
}
fun getGenericVoidTransactions(
transType: Int,
voucherNo: String,
isEmv: Boolean
): LiveData<PayDetail> {
return repository.getGenericVoidTransaction(transType, voucherNo, isEmv)
}
fun getVoidTrans(transType: Int, voucherNo: String): LiveData<PayDetail> {
return repository.getVoidTransaction(transType, voucherNo)
}
fun observeVoidTrans(transType: Int) {
getVoidTransactions(transType).observeForever(object : Observer<List<PayDetail>> {
override fun onChanged(payDetails: List<PayDetail>) {
if (lists.value == null) {
lists.postValue(payDetails)
}
}
})
}
fun searchTransaction(voucherNo: String): LiveData<PayDetail> {
return repository.searchTransaction(voucherNo)
}
fun getLastThreeTransactions(): LiveData<List<PayDetail>> {
return repository.getLastThreeTransactions()
}
}

View File

@ -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()
}

View File

@ -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,