From af917520b67ed5da38430f357797467ffede56ca Mon Sep 17 00:00:00 2001 From: moon <56061215+MgKyawLay@users.noreply.github.com> Date: Fri, 22 May 2026 00:30:51 +0630 Subject: [PATCH] Settlement Screen init --- .../mob/utsmyanmar/model/TransactionStatus.kt | 11 + .../ui/dashboard/DashboardScreen2.kt | 17 +- .../utsmyanmar/ui/navigation/AppNavGraph.kt | 24 + .../mob/utsmyanmar/ui/navigation/Routes.kt | 1 + .../ui/settlement/SettlementScreen.kt | 194 ++++++++ .../ui/settlement/SettlementViewModel.kt | 440 ++++++++++++++++++ .../utsmyanmar/viewmodel/SharedViewModel.kt | 38 ++ 7 files changed, 721 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/mob/utsmyanmar/model/TransactionStatus.kt create mode 100644 app/src/main/java/com/mob/utsmyanmar/ui/settlement/SettlementScreen.kt create mode 100644 app/src/main/java/com/mob/utsmyanmar/ui/settlement/SettlementViewModel.kt diff --git a/app/src/main/java/com/mob/utsmyanmar/model/TransactionStatus.kt b/app/src/main/java/com/mob/utsmyanmar/model/TransactionStatus.kt new file mode 100644 index 0000000..c0d608e --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/model/TransactionStatus.kt @@ -0,0 +1,11 @@ +package com.mob.utsmyanmar.model + +enum class TransactionStatus { + ON_SUCCESS, + ON_REVERSAL, + ON_BATCH_UPLOAD, + ON_FAIL, + ON_ERROR, + ON_SECONDARY, + ON_DONE +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt index fbb2fb8..2a687f5 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt @@ -38,6 +38,7 @@ import androidx.compose.material3.CardDefaults import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.AlertDialog +import androidx.compose.material3.DrawerValue import androidx.compose.material3.ModalDrawerSheet import androidx.compose.material3.ModalNavigationDrawer import androidx.compose.material3.NavigationDrawerItem @@ -85,6 +86,7 @@ fun DashboardScreen2( onNavigateAmount: (String) -> Unit = {}, onNavigateSignOn: () -> Unit = {}, onNavigateSeeMore: () -> Unit = {}, + onNavigateSettlement: () -> Unit = {}, deviceInfoViewModel: DeviceInfoViewModel = viewModel() ) { val deviceInfo by deviceInfoViewModel.uiState.collectAsState() @@ -92,7 +94,7 @@ fun DashboardScreen2( LaunchedEffect(Unit) { deviceInfoViewModel.loadDeviceInfo(); } - val drawerState = rememberDrawerState(initialValue = androidx.compose.material3.DrawerValue.Closed) + val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val scope = rememberCoroutineScope() val mainHandler = remember { Handler(Looper.getMainLooper()) } var showHostActionDialog by remember { mutableStateOf(false) } @@ -301,7 +303,8 @@ fun DashboardScreen2( MenuGrid( onNavigateAmount = onNavigateAmount, onNavigateSignOn = onNavigateSignOn, - onNavigateSeeMore = onNavigateSeeMore + onNavigateSeeMore = onNavigateSeeMore, + onNavigateSettlement = onNavigateSettlement ) } } @@ -496,7 +499,8 @@ private fun IconCircle( private fun MenuGrid( onNavigateAmount: (String) -> Unit, onNavigateSignOn: () -> Unit, - onNavigateSeeMore: () -> Unit + onNavigateSeeMore: () -> Unit, + onNavigateSettlement: () -> Unit ) { Column( verticalArrangement = Arrangement.spacedBy(10.dp), @@ -520,7 +524,12 @@ private fun MenuGrid( Modifier.weight(1f), onClick = onNavigateSignOn ) - MenuCard("Settlement", Icons.Default.Wallet, Modifier.weight(1f)) + MenuCard( + "Settlement", + Icons.Default.Wallet, + Modifier.weight(1f), + onClick = onNavigateSettlement + ) MenuCard( "See More", Icons.Default.GridView, 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 c268d98..649ff9d 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 @@ -23,6 +23,7 @@ import com.mob.utsmyanmar.ui.print_receipt.PrintReceiptScreen 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.settlement.SettlementScreen import com.mob.utsmyanmar.ui.transaction_result.TransactionResultRoute import com.mob.utsmyanmar.ui.sale_void.TranDetailPage import com.mob.utsmyanmar.ui.sale_void.VoidViewModel @@ -63,6 +64,11 @@ fun AppNavGraph( navController.navigate(Routes.SeeMore.route) { launchSingleTop = true } + }, + onNavigateSettlement = { + navController.navigate(Routes.Settlement.route) { + launchSingleTop = true + } } ) } @@ -98,6 +104,24 @@ fun AppNavGraph( ) } + composable(Routes.Settlement.route) { + val sharedViewModel: SharedViewModel = hiltViewModel(activity) + + SettlementScreen( + sharedViewModel = sharedViewModel, + onBack = { navController.popBackStack() }, + onStartSettlement = { + sharedViewModel.transactionsType.value = com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT + navController.navigate(Routes.SendingToHost.route) { + popUpTo(Routes.Settlement.route) { + inclusive = true + } + launchSingleTop = true + } + } + ) + } + composable( route = Routes.VoidTranDetail.route, arguments = listOf( diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/Routes.kt b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/Routes.kt index 31b1e4c..78e74b7 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/Routes.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/Routes.kt @@ -8,6 +8,7 @@ sealed class Routes(val route: String) { fun createRoute(action: String): String = "amount/${Uri.encode(action)}" } data object SeeMore : Routes("see_more") + data object Settlement : Routes("settlement") data object VoidTrace : Routes("void_trace") data object VoidTranDetail : Routes("void_tran_detail/{trace}") { fun createRoute(trace: String): String = "void_tran_detail/${Uri.encode(trace)}" diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/settlement/SettlementScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/settlement/SettlementScreen.kt new file mode 100644 index 0000000..71f2720 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/settlement/SettlementScreen.kt @@ -0,0 +1,194 @@ +package com.mob.utsmyanmar.ui.settlement + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +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 + +@Composable +fun SettlementScreen( + sharedViewModel: SharedViewModel, + onBack: () -> Unit, + onStartSettlement: () -> Unit +) { + val records by sharedViewModel.getSettlementRecords().observeAsState(emptyList()) + val totalAmount = records.sumOf { it.amount } + + Scaffold( + containerColor = Color.IvoryBeige, + topBar = { + AppBar( + title = "Settlement", + icon = Icons.AutoMirrored.Filled.ArrowBack, + onIconClick = onBack + ) + } + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + .padding(16.dp) + ) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = Color.White) + ) { + Column(modifier = Modifier.padding(18.dp)) { + Text( + text = "Settlement Summary", + color = Color.LegacyRed, + fontSize = 18.sp, + fontWeight = FontWeight.Bold + ) + + Spacer(modifier = Modifier.height(12.dp)) + + SummaryRow("Record Count", records.size.toString()) + SummaryRow("Total Amount", POSUtil.getInstance().formatAmount(totalAmount)) + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "Unsettled Records", + color = Color.Black, + fontSize = 15.sp, + fontWeight = FontWeight.SemiBold + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Card( + modifier = Modifier + .fillMaxWidth() + .weight(1f), + colors = CardDefaults.cardColors(containerColor = Color.White) + ) { + if (records.isEmpty()) { + Text( + text = "No records available for settlement.", + color = Color.Gray, + fontSize = 14.sp, + modifier = Modifier.padding(18.dp) + ) + } else { + LazyColumn( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(0.dp) + ) { + items(records) { record -> + SettlementRecordRow(record = record) + } + } + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + Button( + onClick = onStartSettlement, + enabled = records.isNotEmpty(), + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + colors = ButtonDefaults.buttonColors( + containerColor = Color.LegacyRed, + contentColor = Color.White + ) + ) { + Text("Start Settlement") + } + } + } +} + +@Composable +private fun SummaryRow( + label: String, + value: String +) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = label, + color = Color.Gray, + fontSize = 13.sp + ) + Text( + text = value, + color = Color.Black, + fontSize = 13.sp, + fontWeight = FontWeight.Medium + ) + } +} + +@Composable +private fun SettlementRecordRow(record: PayDetail) { + Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = record.transType.ifBlank { "UNKNOWN" }, + color = Color.LegacyRed, + fontSize = 14.sp, + fontWeight = FontWeight.Bold + ) + Text( + text = POSUtil.getInstance().formatAmount(record.amount), + color = Color.Black, + fontSize = 14.sp, + fontWeight = FontWeight.SemiBold + ) + } + + Spacer(modifier = Modifier.height(4.dp)) + + Text( + text = "Trace ${record.voucherNo.ifBlank { "-" }}", + color = Color.Black, + fontSize = 12.sp + ) + Text( + text = "Card ${record.cardNo.ifBlank { "-" }}", + color = Color.Gray, + fontSize = 12.sp + ) + + Spacer(modifier = Modifier.height(12.dp)) + HorizontalDivider(color = Color.Gray.copy(alpha = 0.25f)) + } +} diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/settlement/SettlementViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/settlement/SettlementViewModel.kt new file mode 100644 index 0000000..f951b46 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/settlement/SettlementViewModel.kt @@ -0,0 +1,440 @@ +package com.mob.utsmyanmar.ui.settlement + +import androidx.lifecycle.LiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mob.utsmyanmar.config.Constants +import com.mob.utsmyanmar.model.SettlementType +import com.mob.utsmyanmar.model.TransactionStatus +import com.utsmyanmar.baselib.repo.Repository +import com.utsmyanmar.paylibs.Constant +import com.utsmyanmar.paylibs.batch_upload.BatchListener +import com.utsmyanmar.paylibs.batch_upload.BatchUploadProcess +import com.utsmyanmar.paylibs.isobuilder.ISOMode +import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX +import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion +import com.utsmyanmar.paylibs.model.MsgField +import com.utsmyanmar.paylibs.model.PayDetail +import com.utsmyanmar.paylibs.model.SettleData +import com.utsmyanmar.paylibs.model.TradeData +import com.utsmyanmar.paylibs.network.ISOCallback +import com.utsmyanmar.paylibs.network.ISOSocket +import com.utsmyanmar.paylibs.utils.MessageType +import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation +import com.utsmyanmar.paylibs.utils.enums.HostName +import com.utsmyanmar.paylibs.utils.iso_utils.BitmapConfig +import com.utsmyanmar.paylibs.utils.iso_utils.TransactionType +import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType +import com.utsmyanmar.paylibs.utils.params.Params +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import sunmi.sunmiui.utils.LogUtil +import java.util.Locale +import javax.inject.Inject + +data class SettlementUiState( + val saleCount: Int = 0, + val saleAmount: Long = 0L, + + val preCount: Int = 0, + val preAmount: Long = 0L, + + val refundCount: Int = 0, + val refundAmount: Long = 0L, + + val caCount: Int = 0, + val caAmount: Long = 0L, + + val settlementType: SettlementType? = null, + val isNoData: Boolean = false, + val isSentData: Boolean = false, + val bottomLayout: Int = 0, + + val status: TransactionStatus? = null, + val isLoading: Boolean = false +) + +sealed interface SettlementEvent { + data class ShowStatus(val status: TransactionStatus) : SettlementEvent +} + +@HiltViewModel +class SettlementViewModel @Inject constructor( + private val repository: Repository +) : ViewModel() { + + companion object { + private val TAG = SettlementViewModel::class.java.simpleName + } + + private var payDetail: PayDetail? = null + private var payDetails: List? = null + + private val deleteTrans = arrayListOf() + + private var flag = false + private var errorFlag = false + private var isSecondCall = false + private var batchIndex = 0 + + private var bitmap = "" + + private val isoMsgX: ISOMsgX = + ISOMsgX.ISOMsgXBuilder( + ISOVersion.VERSION_1993, + ISOMode.BOTH_HEADER_TPDU, + HostName.BPC + ).build() + + private val _uiState = MutableStateFlow(SettlementUiState()) + val uiState = _uiState.asStateFlow() + + private val _events = Channel(Channel.BUFFERED) + val events = _events.receiveAsFlow() + + fun getLastSettlement(voucherNo: String): LiveData> { + return repository.getLastSettlement(voucherNo) + } + + fun getSettlement(): LiveData> { + return repository.getSettlement() + } + + fun getSettlementPOS(): LiveData> { + return repository.getSettlementPOS() + } + + fun getDeleteTrans(batchNo: String): LiveData> { + return repository.getDeleteTrans(batchNo) + } + + fun getAdditionalSettlementPOS(): LiveData> { + return repository.getAdditionalSettlementPOS( + SystemParamsOperation.getInstance().getCurrentBatchNum() + ) + } + + fun setPayDetails(list: List) { + payDetails = list + } + + fun setSettlementSummary( + saleCount: Int, + saleAmount: Long, + preCount: Int, + preAmount: Long, + refundCount: Int, + refundAmount: Long, + caCount: Int, + caAmount: Long + ) { + _uiState.update { + it.copy( + saleCount = saleCount, + saleAmount = saleAmount, + preCount = preCount, + preAmount = preAmount, + refundCount = refundCount, + refundAmount = refundAmount, + caCount = caCount, + caAmount = caAmount + ) + } + } + + fun setSettlementType(type: SettlementType) { + _uiState.update { + it.copy(settlementType = type) + } + } + + fun updatePayDetail(payDetail: PayDetail) { + repository.updatePayDetail(payDetail) + } + + private fun insertPayDetail(payDetail: PayDetail) { + repository.insertPayDetail(payDetail) + } + + private fun updateDB() { + payDetails?.forEach { pay -> + repository.deletePayDetail(pay) + } + + deleteTrans.forEach { pay -> + repository.deletePayDetail(pay) + } + + payDetails = emptyList() + deleteTrans.clear() + } + + fun startSettlementProcess() { + _uiState.update { + it.copy(isLoading = true) + } + + SystemParamsOperation.getInstance().getIncrementBatchNo() + + requestOnlineProcessSettlement() + } + + fun startPrintSettlementProcess() { + // PrintReceipt.getInstance().printSettlementReceiptPOS(...) + } + + fun testServiceClass() { + LogUtil.d(TAG, "SettlementViewModel works!") + } + + private fun requestOnlineProcessSettlement() { + val state = _uiState.value + + val hostName = HostName.BPC + val field60 = SystemParamsOperation.getInstance().getCurrentBatchNum() + + val sale2Count = state.saleCount + state.preCount + val sale2Amount = state.saleAmount + state.preAmount + + val totalSaleCount = String.format(Locale.getDefault(), "%03d", sale2Count) + val totalSaleAmount = String.format(Locale.getDefault(), "%010d00", sale2Amount) + + val totalRefundCount = String.format(Locale.getDefault(), "%03d", state.refundCount) + val totalRefundAmount = String.format( + Locale.getDefault(), + "%010d00", + if (state.refundAmount == 0L) 0 else state.refundAmount + ) + + val totalDebitSaleCount = String.format(Locale.getDefault(), "%03d", state.caCount) + val totalDebitSaleAmount = String.format( + Locale.getDefault(), + "%010d00", + if (state.caAmount == 0L) 0 else state.caAmount + ) + + val totalERefundCount = String.format(Locale.getDefault(), "%03d", 0) + val totalERefundAmount = String.format(Locale.getDefault(), "%010d00", 0) + + val tradeData = Params.newTrade(true) + val currentPayDetail = tradeData.payDetail + + payDetail = currentPayDetail + + bitmap = BitmapConfig.BPC_SETTLEMENT + + currentPayDetail.transType = TransactionsType.SETTLEMENT.name + currentPayDetail.transactionType = TransactionType.SETTLEMENT + + if (!flag) { + currentPayDetail.processCode = TransactionsType.SETTLEMENT.processCode + } else { + bitmap = BitmapConfig.BPC_SETTLEMENT_TRAILER + currentPayDetail.processCode = "910000" + } + + currentPayDetail.batchNo = SystemParamsOperation.getInstance().getCurrentBatchNum() + + currentPayDetail.settleList = + "${state.saleCount}:${state.saleAmount}-" + + "${state.caCount}:${state.caAmount}-" + + "${state.refundCount}:${state.refundAmount}-" + + "${state.preCount}:${state.preAmount}" + + val settleData = SettleData( + state.saleCount, + state.saleAmount, + state.preCount, + state.preAmount, + state.refundCount, + state.refundAmount, + state.caCount, + state.caAmount + ) + + currentPayDetail.settleDataObj = settleData + + if (hostName == HostName.BPC) { + val totalAmount = + state.saleAmount + state.preAmount + state.refundAmount + state.caAmount + + val settlementData = if (state.refundAmount != 0L) { + val creditTotal = state.saleAmount + state.preAmount + state.caAmount + val subTotal = creditTotal - state.refundAmount + + if (subTotal < 0L) { + "D" + String.format(Locale.getDefault(), "%012d", kotlin.math.abs(subTotal)) + } else { + "C" + String.format(Locale.getDefault(), "%012d", subTotal) + } + } else { + "C" + String.format(Locale.getDefault(), "%012d", totalAmount) + } + + currentPayDetail.settleData = settlementData + currentPayDetail.amount = totalAmount + } else { + currentPayDetail.settleData = + totalSaleCount + + totalSaleAmount + + totalRefundCount + + totalRefundAmount + + totalDebitSaleCount + + totalDebitSaleAmount + + totalERefundCount + + totalERefundAmount + } + + tradeData.payDetail = currentPayDetail + tradeData.field60 = field60 + + val sendBytes = isoMsgX.buildISOPackets( + tradeData, + bitmap, + MessageType.SETTLEMENT + ) + + LogUtil.d(TAG, "Starting SETTLEMENT process...") + + ISOSocket.getInstance().enqueue( + sendBytes, + sendBytes.size, + false, + object : ISOCallback { + + override fun onReceive(bytes: ByteArray, length: Int) { + val responseMap: Map? = + isoMsgX.parseISOPackets(bytes, length) + + if (responseMap != null) { + val resultStr = try { + responseMap["F039"]?.dataStr.orEmpty() + } catch (e: NullPointerException) { + e.printStackTrace() + currentPayDetail.isNeedReversal = true + return + } + + currentPayDetail.tradeAnswerCode = resultStr + + when { + resultStr == Constant.ANSWER_CODE_ACCEPT || + resultStr == Constant.ANSWER_CODE_APPROVED -> { + currentPayDetail.isNeedReversal = false + } + + resultStr == "95" || resultStr == "095" -> { + currentPayDetail.isNeedReversal = !flag + } + } + } else { + errorFlag = true + } + } + + override fun onError(msg: String) { + if (msg != Constants.REVERSAL) { + if (!isSecondCall) { + ISOSocket.getInstance().switchIp() + + postStatus(TransactionStatus.ON_SECONDARY) + + isSecondCall = true + requestOnlineProcessSettlement() + } else { + postStatus(TransactionStatus.ON_ERROR) + + currentPayDetail.isNeedReversal = true + isSecondCall = false + } + } else { + postStatus(TransactionStatus.ON_ERROR) + } + } + + override fun onComplete() { + if (currentPayDetail.isNeedReversal) { + flag = true + batchUploadProcess() + } else { + flag = false + batchIndex = 0 + + updateDB() + insertPayDetail(currentPayDetail) + + if (errorFlag) { + postStatus(TransactionStatus.ON_ERROR) + } else { + postStatus(TransactionStatus.ON_SUCCESS) + } + + _uiState.update { + it.copy(isLoading = false) + } + } + } + } + ) + } + + private fun batchUploadProcess() { + postStatus(TransactionStatus.ON_BATCH_UPLOAD) + + val currentPayDetails = payDetails + + if (currentPayDetails.isNullOrEmpty()) { + requestOnlineProcessSettlement() + return + } + + val uploadPayDetail = currentPayDetails[batchIndex] + + val tradeData = TradeData().apply { + payDetail = uploadPayDetail + } + + BatchUploadProcess.getInstance() + .enqueue(tradeData) + .startBatchUpload(object : BatchListener { + + override fun onSuccessBatch() { + if (batchIndex < currentPayDetails.size - 1) { + LogUtil.d(TAG, "Pay detail size: ${currentPayDetails.size}") + LogUtil.d(TAG, "Count value: $batchIndex") + + batchIndex++ + batchUploadProcess() + } else { + requestOnlineProcessSettlement() + } + + LogUtil.e(TAG, "Batch Upload Success") + } + + override fun onFailBatch() { + LogUtil.e(TAG, "Batch Upload Fail") + postStatus(TransactionStatus.ON_ERROR) + + _uiState.update { + it.copy(isLoading = false) + } + } + }) + } + + private fun postStatus(status: TransactionStatus) { + _uiState.update { + it.copy(status = status) + } + + viewModelScope.launch { + _events.send(SettlementEvent.ShowStatus(status)) + } + } +} \ No newline at end of file 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 57ff350..c34162c 100644 --- a/app/src/main/java/com/mob/utsmyanmar/viewmodel/SharedViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/viewmodel/SharedViewModel.kt @@ -431,6 +431,10 @@ class SharedViewModel @Inject constructor( return repository.getLastThreeTransactions() } + fun getSettlementRecords(): LiveData> { + return repository.getSettlementPOS() + } + fun getReversalTransaction(voucherNo: String): LiveData { return repository.getReversalTransaction(voucherNo) } @@ -445,6 +449,7 @@ class SharedViewModel @Inject constructor( fun saveMockHostResultForTesting() { when (transactionsType.value) { + TransactionsType.SETTLEMENT -> saveMockSettlementForTesting() TransactionsType.VOID -> saveMockApprovedVoidForTesting() else -> saveMockApprovedSaleForVoidTesting() } @@ -553,6 +558,39 @@ class SharedViewModel @Inject constructor( approvalCode.value = mockApprovalCode } + fun saveMockSettlementForTesting() { + val systemParams = SystemParamsOperation.getInstance() + val mockTraceNo = systemParams.incrementSerialNum + val mockInvoiceNo = systemParams.incrementInvoiceNum + + val settlementDetail = PayDetail().apply { + merchantNo = systemParams.merchantId + merchantName = systemParams.merchantName + terminalNo = systemParams.terminalId + voucherNo = mockTraceNo + invoiceNo = mockInvoiceNo + batchNo = systemParams.systemParamsSettings.batchNumStart + processCode = TransactionsType.SETTLEMENT.processCode + transactionType = TransactionType.SETTLEMENT + transType = TransactionsType.SETTLEMENT.name + currencyCode = systemParams.currencyType.removed0CurrencyCode + tradeAnswerCode = "00" + tradeResultDes = "MOCK SETTLEMENT APPROVED" + TradeDate = SystemDateTime.getMMDD() + TradeTime = SystemDateTime.getHHmmss() + tradeDateAndTime = SystemDateTime.getMMDDhhmmss() + tradeDateTime = SystemDateTime.getYYMMDDhhmmss() + transDate = SystemDateTime.getTodayDateFormat() + transTime = SystemDateTime.getTodayTimeFormat() + isSettle = false + isNeedReversal = false + isCanceled = false + } + + payDetail.value = settlementDetail + traceNo.value = mockTraceNo + } + fun enableCardStatusIcon( tapCard: Boolean, tapDevice: Boolean,