void flow complete
This commit is contained in:
parent
5c6c8f78c5
commit
767456b29a
@ -24,6 +24,7 @@ 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.sale_void.TranDetailPage
|
||||
import com.mob.utsmyanmar.ui.sale_void.VoidViewModel
|
||||
import com.mob.utsmyanmar.ui.sale_void.VoidTraceScreen
|
||||
import com.mob.utsmyanmar.viewmodel.CardReaderViewModel
|
||||
@ -88,10 +89,44 @@ fun AppNavGraph(
|
||||
|
||||
VoidTraceScreen(
|
||||
voidViewModel = voidViewModel,
|
||||
onNavigateTranDetail = { trace ->
|
||||
navController.navigate(Routes.VoidTranDetail.createRoute(trace)) {
|
||||
launchSingleTop = true
|
||||
}
|
||||
},
|
||||
onBack = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
|
||||
composable(
|
||||
route = Routes.VoidTranDetail.route,
|
||||
arguments = listOf(
|
||||
navArgument("trace") {
|
||||
type = NavType.StringType
|
||||
}
|
||||
)
|
||||
) { backStackEntry ->
|
||||
val voidViewModel: VoidViewModel = hiltViewModel()
|
||||
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
||||
val trace = backStackEntry.arguments?.getString("trace").orEmpty()
|
||||
|
||||
TranDetailPage(
|
||||
voidViewModel = voidViewModel,
|
||||
trace = trace,
|
||||
onBack = { navController.popBackStack() },
|
||||
onProceedVoid = { payDetail ->
|
||||
sharedViewModel.transactionsType.value = com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.VOID
|
||||
sharedViewModel.payDetail.value = payDetail
|
||||
navController.navigate(Routes.SendingToHost.route) {
|
||||
popUpTo(Routes.VoidTranDetail.route) {
|
||||
inclusive = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(Routes.SignOn.route) {
|
||||
SignOnRoute(
|
||||
onBack = { navController.popBackStack() },
|
||||
|
||||
@ -9,6 +9,9 @@ sealed class Routes(val route: String) {
|
||||
}
|
||||
data object SeeMore : Routes("see_more")
|
||||
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)}"
|
||||
}
|
||||
data object SignOn : Routes("sign_on")
|
||||
data object SignOnResult : Routes("sign_on_result/{isSuccess}/{message}") {
|
||||
fun createRoute(isSuccess: Boolean, message: String): String {
|
||||
|
||||
@ -0,0 +1,168 @@
|
||||
package com.mob.utsmyanmar.ui.sale_void
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
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.shape.RoundedCornerShape
|
||||
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.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.Alignment
|
||||
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.utsmyanmar.paylibs.model.PayDetail
|
||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||
|
||||
@Composable
|
||||
fun TranDetailPage(
|
||||
voidViewModel: VoidViewModel,
|
||||
trace: String,
|
||||
onBack: () -> Unit,
|
||||
onProceedVoid: (PayDetail) -> Unit
|
||||
) {
|
||||
val transaction by voidViewModel.searchTransaction(trace).observeAsState()
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Transaction Detail",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
transaction?.let { payDetail ->
|
||||
TransactionDetailsCard(transaction = payDetail)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Text(
|
||||
text = "Review the transaction before proceeding to void.",
|
||||
color = Color.Gray,
|
||||
fontSize = 13.sp
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
Button(
|
||||
onClick = onBack,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.height(56.dp),
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.White,
|
||||
contentColor = Color.LegacyRed
|
||||
)
|
||||
) {
|
||||
Text("Back")
|
||||
}
|
||||
|
||||
Button(
|
||||
onClick = { onProceedVoid(payDetail) },
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.height(56.dp),
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.LegacyRed,
|
||||
contentColor = Color.White
|
||||
)
|
||||
) {
|
||||
Text("Void")
|
||||
}
|
||||
}
|
||||
} ?: Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = "Transaction not found.",
|
||||
color = Color.Gray,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TransactionDetailsCard(transaction: PayDetail) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "Previous Sale",
|
||||
color = Color.LegacyRed,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
|
||||
DetailRow("Trace", transaction.voucherNo)
|
||||
DetailRow("Amount", POSUtil.getInstance().formatAmount(transaction.amount))
|
||||
DetailRow("Card No", transaction.cardNo)
|
||||
DetailRow("Reference", transaction.referNo)
|
||||
DetailRow("Approval", transaction.approvalCode.orEmpty())
|
||||
DetailRow("Date", transaction.tradeDate)
|
||||
DetailRow("Time", transaction.tradeTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DetailRow(
|
||||
label: String,
|
||||
value: String
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
color = Color.Gray,
|
||||
fontSize = 13.sp
|
||||
)
|
||||
Text(
|
||||
text = value.ifBlank { "-" },
|
||||
color = Color.Black,
|
||||
fontSize = 13.sp,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -41,17 +41,18 @@ import androidx.lifecycle.MutableLiveData
|
||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||
import com.mob.utsmyanmar.ui.theme.Color
|
||||
import com.utsmyanmar.paylibs.model.PayDetail
|
||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||
|
||||
@Composable
|
||||
fun VoidTraceScreen(
|
||||
voidViewModel: VoidViewModel,
|
||||
onNavigateTranDetail: (String) -> Unit,
|
||||
onBack: () -> Unit = {}
|
||||
) {
|
||||
val tag = "VoidTraceScreen"
|
||||
var traceNumber by remember { mutableStateOf("") }
|
||||
var searchedTrace by remember { mutableStateOf("") }
|
||||
var lastNavigatedTrace by remember { mutableStateOf<String?>(null) }
|
||||
val displayTraceNumber = traceNumber.padStart(6, '0').ifEmpty { "000000" }
|
||||
val recentTransactions by voidViewModel.getLastThreeTransactions().observeAsState(emptyList())
|
||||
|
||||
@ -78,6 +79,19 @@ fun VoidTraceScreen(
|
||||
} else {
|
||||
Color.Black
|
||||
}
|
||||
|
||||
LaunchedEffect(searchedTrace) {
|
||||
if (searchedTrace != lastNavigatedTrace) {
|
||||
lastNavigatedTrace = null
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(transaction?.voucherNo) {
|
||||
val matchedTrace = transaction?.voucherNo ?: return@LaunchedEffect
|
||||
if (lastNavigatedTrace == matchedTrace) return@LaunchedEffect
|
||||
lastNavigatedTrace = matchedTrace
|
||||
onNavigateTranDetail(matchedTrace)
|
||||
}
|
||||
|
||||
|
||||
LaunchedEffect(searchedTrace, transaction) {
|
||||
@ -162,13 +176,7 @@ fun VoidTraceScreen(
|
||||
}
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
if (transaction != null) {
|
||||
TransactionDetailsCard(transaction = transaction!!)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
@ -303,55 +311,3 @@ private fun TraceKeypadButton(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TransactionDetailsCard(transaction: PayDetail) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "Previous Sale",
|
||||
color = Color.LegacyRed,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
|
||||
DetailRow("Trace", transaction.voucherNo)
|
||||
DetailRow("Amount", POSUtil.getInstance().formatAmount(transaction.amount))
|
||||
DetailRow("Card No", transaction.cardNo)
|
||||
DetailRow("Reference", transaction.referNo)
|
||||
DetailRow("Approval", transaction.approvalCode.orEmpty())
|
||||
DetailRow("Date", transaction.tradeDate)
|
||||
DetailRow("Time", transaction.tradeTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
private fun DetailRow(
|
||||
label: String,
|
||||
value: String
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = label,
|
||||
color = Color.Gray,
|
||||
fontSize = 13.sp
|
||||
)
|
||||
Text(
|
||||
text = value.ifBlank { "-" },
|
||||
color = Color.Black,
|
||||
fontSize = 13.sp,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ fun SendingToHostRoute(
|
||||
onNavigateTransactionResult: () -> Unit
|
||||
) {
|
||||
LaunchedEffect(Unit) {
|
||||
sharedViewModel.saveMockApprovedSaleForVoidTesting()
|
||||
sharedViewModel.saveMockHostResultForTesting()
|
||||
delay(MOCK_HOST_DELAY_MS)
|
||||
onNavigateTransactionResult()
|
||||
}
|
||||
|
||||
@ -443,6 +443,13 @@ class SharedViewModel @Inject constructor(
|
||||
repository.insertPayDetail(payDetail)
|
||||
}
|
||||
|
||||
fun saveMockHostResultForTesting() {
|
||||
when (transactionsType.value) {
|
||||
TransactionsType.VOID -> saveMockApprovedVoidForTesting()
|
||||
else -> saveMockApprovedSaleForVoidTesting()
|
||||
}
|
||||
}
|
||||
|
||||
fun saveMockApprovedSaleForVoidTesting() {
|
||||
val detail = payDetail.value ?: return
|
||||
|
||||
@ -482,6 +489,70 @@ class SharedViewModel @Inject constructor(
|
||||
approvalCode.value = mockApprovalCode
|
||||
}
|
||||
|
||||
fun saveMockApprovedVoidForTesting() {
|
||||
val originalSale = payDetail.value ?: return
|
||||
|
||||
originalSale.isCanceled = true
|
||||
repository.updatePayDetail(originalSale)
|
||||
|
||||
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)
|
||||
|
||||
val voidDetail = PayDetail().apply {
|
||||
merchantName = originalSale.merchantName
|
||||
merchantNo = originalSale.merchantNo
|
||||
terminalNo = originalSale.terminalNo
|
||||
CardNo = originalSale.CardNo
|
||||
cardType = originalSale.cardType
|
||||
EXPDate = originalSale.EXPDate
|
||||
cardHolderName = originalSale.cardHolderName
|
||||
processCode = TransactionsType.VOID.processCode
|
||||
amount = originalSale.amount
|
||||
transPlatform = originalSale.transPlatform
|
||||
transactionType = TransactionType.VOID
|
||||
transType = TransactionsType.VOID.name
|
||||
currencyCode = originalSale.currencyCode
|
||||
currency = originalSale.currency
|
||||
batchNo = originalSale.batchNo
|
||||
voucherNo = mockTraceNo
|
||||
invoiceNo = mockInvoiceNo
|
||||
referNo = mockReferenceNo
|
||||
approvalCode = mockApprovalCode
|
||||
authNo = mockApprovalCode
|
||||
accountType = originalSale.accountType
|
||||
tradeAnswerCode = "00"
|
||||
tradeResultDes = "MOCK VOID APPROVED"
|
||||
TradeDate = SystemDateTime.getMMDD()
|
||||
TradeTime = SystemDateTime.getHHmmss()
|
||||
tradeDateAndTime = SystemDateTime.getMMDDhhmmss()
|
||||
tradeDateTime = SystemDateTime.getYYMMDDhhmmss()
|
||||
transDate = SystemDateTime.getTodayDateFormat()
|
||||
transTime = SystemDateTime.getTodayTimeFormat()
|
||||
originalPOSNum = originalSale.voucherNo
|
||||
originalReferNo = originalSale.referNo
|
||||
originalAuthNo = originalSale.approvalCode
|
||||
originalBathNo = originalSale.batchNo
|
||||
originalTransDate = originalSale.TradeDate
|
||||
originalAmount = originalSale.amount
|
||||
isCanceled = false
|
||||
isSettle = false
|
||||
isNeedReversal = false
|
||||
isReturnGood = false
|
||||
}
|
||||
|
||||
repository.insertPayDetail(voidDetail)
|
||||
payDetail.value = voidDetail
|
||||
traceNo.value = mockTraceNo
|
||||
rrNNo.value = mockReferenceNo
|
||||
approvalCode.value = mockApprovalCode
|
||||
}
|
||||
|
||||
fun enableCardStatusIcon(
|
||||
tapCard: Boolean,
|
||||
tapDevice: Boolean,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user