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.sign_on.SignOnRoute
|
||||||
import com.mob.utsmyanmar.ui.sending_to_host.SendingToHostRoute
|
import com.mob.utsmyanmar.ui.sending_to_host.SendingToHostRoute
|
||||||
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultRoute
|
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.VoidViewModel
|
||||||
import com.mob.utsmyanmar.ui.sale_void.VoidTraceScreen
|
import com.mob.utsmyanmar.ui.sale_void.VoidTraceScreen
|
||||||
import com.mob.utsmyanmar.viewmodel.CardReaderViewModel
|
import com.mob.utsmyanmar.viewmodel.CardReaderViewModel
|
||||||
@ -88,10 +89,44 @@ fun AppNavGraph(
|
|||||||
|
|
||||||
VoidTraceScreen(
|
VoidTraceScreen(
|
||||||
voidViewModel = voidViewModel,
|
voidViewModel = voidViewModel,
|
||||||
|
onNavigateTranDetail = { trace ->
|
||||||
|
navController.navigate(Routes.VoidTranDetail.createRoute(trace)) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
onBack = { navController.popBackStack() }
|
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) {
|
composable(Routes.SignOn.route) {
|
||||||
SignOnRoute(
|
SignOnRoute(
|
||||||
onBack = { navController.popBackStack() },
|
onBack = { navController.popBackStack() },
|
||||||
|
|||||||
@ -9,6 +9,9 @@ sealed class Routes(val route: String) {
|
|||||||
}
|
}
|
||||||
data object SeeMore : Routes("see_more")
|
data object SeeMore : Routes("see_more")
|
||||||
data object VoidTrace : Routes("void_trace")
|
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 SignOn : Routes("sign_on")
|
||||||
data object SignOnResult : Routes("sign_on_result/{isSuccess}/{message}") {
|
data object SignOnResult : Routes("sign_on_result/{isSuccess}/{message}") {
|
||||||
fun createRoute(isSuccess: Boolean, message: String): String {
|
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.components.appbar.AppBar
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
import com.utsmyanmar.paylibs.model.PayDetail
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
|
||||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VoidTraceScreen(
|
fun VoidTraceScreen(
|
||||||
voidViewModel: VoidViewModel,
|
voidViewModel: VoidViewModel,
|
||||||
|
onNavigateTranDetail: (String) -> Unit,
|
||||||
onBack: () -> Unit = {}
|
onBack: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val tag = "VoidTraceScreen"
|
val tag = "VoidTraceScreen"
|
||||||
var traceNumber by remember { mutableStateOf("") }
|
var traceNumber by remember { mutableStateOf("") }
|
||||||
var searchedTrace by remember { mutableStateOf("") }
|
var searchedTrace by remember { mutableStateOf("") }
|
||||||
|
var lastNavigatedTrace by remember { mutableStateOf<String?>(null) }
|
||||||
val displayTraceNumber = traceNumber.padStart(6, '0').ifEmpty { "000000" }
|
val displayTraceNumber = traceNumber.padStart(6, '0').ifEmpty { "000000" }
|
||||||
val recentTransactions by voidViewModel.getLastThreeTransactions().observeAsState(emptyList())
|
val recentTransactions by voidViewModel.getLastThreeTransactions().observeAsState(emptyList())
|
||||||
|
|
||||||
@ -78,6 +79,19 @@ fun VoidTraceScreen(
|
|||||||
} else {
|
} else {
|
||||||
Color.Black
|
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) {
|
LaunchedEffect(searchedTrace, transaction) {
|
||||||
@ -162,13 +176,7 @@ fun VoidTraceScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
Column(modifier = Modifier.weight(1f)) {
|
|
||||||
if (transaction != null) {
|
|
||||||
TransactionDetailsCard(transaction = transaction!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
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
|
onNavigateTransactionResult: () -> Unit
|
||||||
) {
|
) {
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
sharedViewModel.saveMockApprovedSaleForVoidTesting()
|
sharedViewModel.saveMockHostResultForTesting()
|
||||||
delay(MOCK_HOST_DELAY_MS)
|
delay(MOCK_HOST_DELAY_MS)
|
||||||
onNavigateTransactionResult()
|
onNavigateTransactionResult()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -443,6 +443,13 @@ class SharedViewModel @Inject constructor(
|
|||||||
repository.insertPayDetail(payDetail)
|
repository.insertPayDetail(payDetail)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun saveMockHostResultForTesting() {
|
||||||
|
when (transactionsType.value) {
|
||||||
|
TransactionsType.VOID -> saveMockApprovedVoidForTesting()
|
||||||
|
else -> saveMockApprovedSaleForVoidTesting()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun saveMockApprovedSaleForVoidTesting() {
|
fun saveMockApprovedSaleForVoidTesting() {
|
||||||
val detail = payDetail.value ?: return
|
val detail = payDetail.value ?: return
|
||||||
|
|
||||||
@ -482,6 +489,70 @@ class SharedViewModel @Inject constructor(
|
|||||||
approvalCode.value = mockApprovalCode
|
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(
|
fun enableCardStatusIcon(
|
||||||
tapCard: Boolean,
|
tapCard: Boolean,
|
||||||
tapDevice: Boolean,
|
tapDevice: Boolean,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user