Compare commits
6 Commits
907eab4e72
...
0234c05e63
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0234c05e63 | ||
|
|
1d2585f548 | ||
|
|
3e6a0707d8 | ||
|
|
4dee4bb6f9 | ||
|
|
a2e2829649 | ||
|
|
d59933f00a |
@ -40,8 +40,8 @@ android {
|
|||||||
dimension = "env"
|
dimension = "env"
|
||||||
applicationIdSuffix = ".uat"
|
applicationIdSuffix = ".uat"
|
||||||
versionNameSuffix = "-UAT"
|
versionNameSuffix = "-UAT"
|
||||||
versionCode = 21
|
versionCode = 29
|
||||||
versionName = "3.9"
|
versionName = "4.7"
|
||||||
buildConfigField("String", "ENV", "\"UAT\"")
|
buildConfigField("String", "ENV", "\"UAT\"")
|
||||||
resValue("string", "app_name", "MOB-UAT")
|
resValue("string", "app_name", "MOB-UAT")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,21 +10,28 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.Backspace
|
import androidx.compose.material.icons.automirrored.rounded.Backspace
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.ui.draw.shadow
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
|
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
|
||||||
import com.mob.utsmyanmar.utils.convertDateString
|
import com.mob.utsmyanmar.utils.convertDateString
|
||||||
import com.utsmyanmar.paylibs.model.PayDetail
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
|
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun HistoryTransactionCard(
|
internal fun HistoryTransactionCard(
|
||||||
@ -44,13 +51,32 @@ internal fun HistoryTransactionCard(
|
|||||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = displayTransactionTitle(payDetail),
|
||||||
|
color = Color.LegacyRed,
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = displayTransactionTitle(payDetail),
|
text = "Date & Time",
|
||||||
color = Color.LegacyRed,
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
"${convertDateString(payDetail.transDate.orEmpty())} ${payDetail.transTime.orEmpty()}".trim(),
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Amount",
|
||||||
style = MaterialTheme.typography.titleSmall
|
style = MaterialTheme.typography.titleSmall
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
@ -59,55 +85,172 @@ internal fun HistoryTransactionCard(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text("Trace ${payDetail.voucherNo.ifBlank { "-" }}", style = MaterialTheme.typography.bodySmall)
|
|
||||||
Text("RRN ${payDetail.referNo.ifBlank { "-" }}", style = MaterialTheme.typography.bodySmall, color = Color.Gray)
|
|
||||||
Text(
|
|
||||||
"${convertDateString(payDetail.transDate)} ${payDetail.transTime}",
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = Color.Gray
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun HistoryTransactionDetailCard(payDetail: PayDetail) {
|
|
||||||
Card(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = displayTransactionTitle(payDetail),
|
|
||||||
color = Color.LegacyRed,
|
|
||||||
style = MaterialTheme.typography.titleMedium
|
|
||||||
)
|
|
||||||
SummaryLine("Date", payDetail.tradeDate)
|
|
||||||
SummaryLine("Time", payDetail.tradeTime)
|
|
||||||
SummaryLine("Amount", displayAmountWithSign(payDetail))
|
|
||||||
SummaryLine("Trace No", payDetail.voucherNo)
|
|
||||||
// SummaryLine("Card No", payDetail.cardNo)
|
|
||||||
SummaryLine("Reference No", payDetail.referNo)
|
|
||||||
SummaryLine("Approval Code", payDetail.approvalCode.orEmpty())
|
|
||||||
SummaryLine("Status", displayTransactionStatus(payDetail))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun SummaryLine(label: String, value: String) {
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
Text(label, color = Color.Gray, style = MaterialTheme.typography.bodyMedium)
|
|
||||||
Text(
|
Text(
|
||||||
value.ifBlank { "-" },
|
text = "Trace No",
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = payDetail.voucherNo.orEmpty().ifBlank { "-" },
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Reference No",
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = payDetail.referNo.orEmpty().ifBlank { "-" },
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Approval Code",
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = (payDetail.approvalCode ?: payDetail.authNo).orEmpty().ifBlank { "-" },
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun HistoryTransactionDetailCard(
|
||||||
|
payDetail: PayDetail,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
val dateStr = if (!payDetail.transDate.isNullOrBlank()) {
|
||||||
|
convertDateString(payDetail.transDate)
|
||||||
|
} else {
|
||||||
|
payDetail.tradeDate.orEmpty().ifBlank { "-" }
|
||||||
|
}
|
||||||
|
val timeStr = payDetail.transTime.orEmpty().ifBlank { payDetail.tradeTime.orEmpty() }.ifBlank { "-" }
|
||||||
|
val merchantNameStr = payDetail.merchantName?.takeIf { it.isNotBlank() }
|
||||||
|
?: SystemParamsOperation.getInstance().merchantName?.takeIf { it.isNotBlank() }
|
||||||
|
?: "-"
|
||||||
|
val midStr = payDetail.merchantNo?.takeIf { it.isNotBlank() }
|
||||||
|
?: SystemParamsOperation.getInstance().merchantId?.takeIf { it.isNotBlank() }
|
||||||
|
?: "-"
|
||||||
|
val tidStr = payDetail.terminalNo?.takeIf { it.isNotBlank() }
|
||||||
|
?: SystemParamsOperation.getInstance().terminalId?.takeIf { it.isNotBlank() }
|
||||||
|
?: "-"
|
||||||
|
val traceNoStr = payDetail.voucherNo.orEmpty().ifBlank { "-" }
|
||||||
|
val refNoStr = payDetail.referNo.orEmpty().ifBlank { "-" }
|
||||||
|
val aprCodeStr = payDetail.approvalCode?.takeIf { it.isNotBlank() }
|
||||||
|
?: payDetail.authNo?.takeIf { it.isNotBlank() }
|
||||||
|
?: "-"
|
||||||
|
val transTypeStr = displayTransactionTitle(payDetail)
|
||||||
|
val amountStr = displayAmountWithSign(payDetail)
|
||||||
|
val cardTypeStr = payDetail.accountType.orEmpty().ifBlank { "-" }
|
||||||
|
val cleanPan = payDetail.cardNo.orEmpty().replace(" ", "")
|
||||||
|
val cardNoStr = if (cleanPan.length > 10) {
|
||||||
|
cleanPan.take(6) + "*".repeat(cleanPan.length - 10) + cleanPan.takeLast(4)
|
||||||
|
} else if (cleanPan.isNotBlank()) {
|
||||||
|
cleanPan
|
||||||
|
} else {
|
||||||
|
"-"
|
||||||
|
}
|
||||||
|
val statusStr = displayTransactionStatus(payDetail)
|
||||||
|
|
||||||
|
Card(
|
||||||
|
modifier = modifier.fillMaxWidth(),
|
||||||
|
shape = RoundedCornerShape(12.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.White),
|
||||||
|
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = transTypeStr,
|
||||||
|
color = Color.LegacyRed,
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
// Text(
|
||||||
|
// text = amountStr,
|
||||||
|
// color = Color.Black,
|
||||||
|
// style = MaterialTheme.typography.titleMedium,
|
||||||
|
// fontWeight = FontWeight.Bold
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
|
||||||
|
HorizontalDivider(
|
||||||
|
modifier = Modifier.padding(vertical = 2.dp),
|
||||||
|
color = Color.Gray.copy(alpha = 0.2f)
|
||||||
|
)
|
||||||
|
|
||||||
|
SummaryLine("Date", dateStr)
|
||||||
|
SummaryLine("Time", timeStr)
|
||||||
|
// SummaryLine("Merchant Name", merchantNameStr)
|
||||||
|
SummaryLine("Mid", midStr)
|
||||||
|
SummaryLine("Tid", tidStr)
|
||||||
|
SummaryLine("Trace No", traceNoStr)
|
||||||
|
SummaryLine("Ref No", refNoStr)
|
||||||
|
SummaryLine("APR Code", aprCodeStr)
|
||||||
|
SummaryLine("Transaction Type", transTypeStr)
|
||||||
|
SummaryLine("Amount", amountStr)
|
||||||
|
SummaryLine("Card Type", cardTypeStr)
|
||||||
|
SummaryLine("Card No", cardNoStr)
|
||||||
|
SummaryLine(
|
||||||
|
label = "Status",
|
||||||
|
value = statusStr,
|
||||||
|
valueColor = when {
|
||||||
|
statusStr.contains("SUCCESS", ignoreCase = true) ||
|
||||||
|
statusStr.contains("Approved", ignoreCase = true) -> Color.Success
|
||||||
|
statusStr.contains("FAIL", ignoreCase = true) ||
|
||||||
|
statusStr.contains("DECLINE", ignoreCase = true) -> Color.Error
|
||||||
|
else -> Color.Black
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun SummaryLine(
|
||||||
|
label: String,
|
||||||
|
value: String,
|
||||||
|
valueColor: androidx.compose.ui.graphics.Color = Color.Black,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
color = Color.Gray,
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
|
Text(
|
||||||
|
text = value.ifBlank { "-" },
|
||||||
|
color = valueColor,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
fontWeight = FontWeight.Medium
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +317,7 @@ internal fun HistoryNumericKeypad(
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (key == "⌫") {
|
if (key == "⌫") {
|
||||||
Icon(Icons.Rounded.Backspace, contentDescription = "Backspace")
|
Icon(Icons.AutoMirrored.Rounded.Backspace, contentDescription = "Backspace")
|
||||||
} else {
|
} else {
|
||||||
Text(key, style = MaterialTheme.typography.headlineMedium)
|
Text(key, style = MaterialTheme.typography.headlineMedium)
|
||||||
}
|
}
|
||||||
@ -184,3 +327,89 @@ internal fun HistoryNumericKeypad(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val searchKeys = listOf(
|
||||||
|
listOf("1", "2", "3"),
|
||||||
|
listOf("4", "5", "6"),
|
||||||
|
listOf("7", "8", "9"),
|
||||||
|
listOf("C", "0", "\u232B")
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun SearchInputBox(
|
||||||
|
query: String,
|
||||||
|
isFocused: Boolean,
|
||||||
|
onFocus: () -> Unit,
|
||||||
|
label: String = if (isFocused) "Trace or RRN" else "Tap to search by Trace or RRN",
|
||||||
|
onDelete: (() -> Unit)? = null,
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable(onClick = onFocus),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.White),
|
||||||
|
shape = RoundedCornerShape(12.dp),
|
||||||
|
elevation = CardDefaults.cardElevation(defaultElevation = if (isFocused) 6.dp else 2.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 14.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = if (isFocused) Color.LegacyRed else Color.Gray
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = query.ifEmpty { "_" },
|
||||||
|
color = Color.LegacyRed,
|
||||||
|
style = MaterialTheme.typography.headlineSmall.copy(
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
letterSpacing = 2.sp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.isNotEmpty()) {
|
||||||
|
Card(
|
||||||
|
shape = RoundedCornerShape(18.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.White),
|
||||||
|
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.shadow(2.dp, RoundedCornerShape(18.dp))
|
||||||
|
.clickable(enabled = onDelete != null) { onDelete?.invoke() }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Rounded.Backspace,
|
||||||
|
contentDescription = "Delete",
|
||||||
|
tint = Color.LegacyRed,
|
||||||
|
modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun HistoryTransactionCardPreview() {
|
||||||
|
MOBPOSTheme {
|
||||||
|
HistoryTransactionCard(
|
||||||
|
payDetail = PayDetail().apply {
|
||||||
|
transDate = "21/09/26"
|
||||||
|
transTime = "14:04:15"
|
||||||
|
voucherNo = "000001"
|
||||||
|
referNo = "123456789012"
|
||||||
|
transType = "SALE"
|
||||||
|
amount = 1500000L
|
||||||
|
},
|
||||||
|
onClick = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -55,11 +55,17 @@ internal fun displayTransactionStatus(payDetail: PayDetail): String {
|
|||||||
if (payDetail.transactionType == TransactionsType.REVERSAL.value) {
|
if (payDetail.transactionType == TransactionsType.REVERSAL.value) {
|
||||||
return if (payDetail.isNeedReversal) "REVERSAL FAILED" else "REVERSAL SUCCESS"
|
return if (payDetail.isNeedReversal) "REVERSAL FAILED" else "REVERSAL SUCCESS"
|
||||||
}
|
}
|
||||||
return POSUtil.getInstance().getResponse(payDetail.tradeAnswerCode.orEmpty().ifBlank { "-" })
|
val code = payDetail.tradeAnswerCode.orEmpty().ifBlank { "-" }
|
||||||
|
return try {
|
||||||
|
POSUtil.getInstance().getResponse(code)
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
if (code == "00") "Approved" else code
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun displayTransactionTitle(payDetail: PayDetail): String {
|
internal fun displayTransactionTitle(payDetail: PayDetail): String {
|
||||||
val title = payDetail.transType
|
val title = payDetail.transType
|
||||||
|
.orEmpty()
|
||||||
.ifBlank { "TRANSACTION" }
|
.ifBlank { "TRANSACTION" }
|
||||||
.replace("CASH_OUT", "CASH_ADV", ignoreCase = true)
|
.replace("CASH_OUT", "CASH_ADV", ignoreCase = true)
|
||||||
return if (payDetail.transactionType == TransactionsType.REVERSAL.value) {
|
return if (payDetail.transactionType == TransactionsType.REVERSAL.value) {
|
||||||
|
|||||||
@ -159,7 +159,8 @@ fun HistoryRoute(
|
|||||||
is HistoryDestination.ReviewDetail -> ReviewDetailScreen(
|
is HistoryDestination.ReviewDetail -> ReviewDetailScreen(
|
||||||
viewModel = viewModel,
|
viewModel = viewModel,
|
||||||
trace = current.trace,
|
trace = current.trace,
|
||||||
onBack = { destination = HistoryDestination.ReviewTrace }
|
onBack = { destination = HistoryDestination.ReviewTrace },
|
||||||
|
onReprint = ::reprintTransaction
|
||||||
)
|
)
|
||||||
|
|
||||||
HistoryDestination.BatchTotal -> BatchTotalScreen(
|
HistoryDestination.BatchTotal -> BatchTotalScreen(
|
||||||
|
|||||||
@ -21,6 +21,7 @@ class HistoryViewModel @Inject constructor(
|
|||||||
fun getLastSettlement(): LiveData<List<PayDetail>> =
|
fun getLastSettlement(): LiveData<List<PayDetail>> =
|
||||||
repository.getLastSettlement()
|
repository.getLastSettlement()
|
||||||
|
|
||||||
|
|
||||||
fun getReviewBatchTransaction(batchNo: String): LiveData<List<PayDetail>> =
|
fun getReviewBatchTransaction(batchNo: String): LiveData<List<PayDetail>> =
|
||||||
repository.getReviewBatchTransaction(batchNo)
|
repository.getReviewBatchTransaction(batchNo)
|
||||||
|
|
||||||
@ -28,5 +29,9 @@ class HistoryViewModel @Inject constructor(
|
|||||||
repository.getSmileSummaryTrans(batchNo)
|
repository.getSmileSummaryTrans(batchNo)
|
||||||
|
|
||||||
fun searchTransaction(voucherNo: String): LiveData<PayDetail> =
|
fun searchTransaction(voucherNo: String): LiveData<PayDetail> =
|
||||||
repository.searchTransaction(voucherNo)
|
if (voucherNo.length > 6) {
|
||||||
|
repository.searchPayDetail(voucherNo)
|
||||||
|
} else {
|
||||||
|
repository.searchTransaction(voucherNo.padStart(6, '0'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,25 +39,15 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.mob.utsmyanmar.ui.components.NumericKeypad
|
import com.mob.utsmyanmar.ui.components.NumericKeypad
|
||||||
import com.mob.utsmyanmar.ui.preview.P2Preview
|
|
||||||
import com.mob.utsmyanmar.ui.preview.P3Preview
|
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
|
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
|
||||||
import com.utsmyanmar.paylibs.model.PayDetail
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
import com.utsmyanmar.paylibs.utils.enums.HostType
|
import com.utsmyanmar.paylibs.utils.enums.HostType
|
||||||
|
|
||||||
private val searchKeys = listOf(
|
|
||||||
listOf("1", "2", "3"),
|
|
||||||
listOf("4", "5", "6"),
|
|
||||||
listOf("7", "8", "9"),
|
|
||||||
listOf("C", "0", "\u232B")
|
|
||||||
)
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReprintAnyTransactionScreen(
|
fun ReprintAnyTransactionScreen(
|
||||||
viewModel: HistoryViewModel,
|
viewModel: HistoryViewModel,
|
||||||
@ -66,6 +56,22 @@ fun ReprintAnyTransactionScreen(
|
|||||||
onReprintTransaction: (PayDetail) -> Unit,
|
onReprintTransaction: (PayDetail) -> Unit,
|
||||||
) {
|
) {
|
||||||
val allTransactions by viewModel.getTransactionHistory().observeAsState(emptyList())
|
val allTransactions by viewModel.getTransactionHistory().observeAsState(emptyList())
|
||||||
|
ReprintAnyTransactionContent(
|
||||||
|
allTransactions = allTransactions,
|
||||||
|
hostType = hostType,
|
||||||
|
onBack = onBack,
|
||||||
|
onReprintTransaction = onReprintTransaction
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ReprintAnyTransactionContent(
|
||||||
|
allTransactions: List<PayDetail>,
|
||||||
|
hostType: HostType,
|
||||||
|
onBack: () -> Unit,
|
||||||
|
onReprintTransaction: (PayDetail) -> Unit,
|
||||||
|
) {
|
||||||
var searchQuery by remember { mutableStateOf("") }
|
var searchQuery by remember { mutableStateOf("") }
|
||||||
var isFocused by remember { mutableStateOf(false) }
|
var isFocused by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
@ -115,7 +121,8 @@ fun ReprintAnyTransactionScreen(
|
|||||||
SearchInputBox(
|
SearchInputBox(
|
||||||
query = searchQuery,
|
query = searchQuery,
|
||||||
isFocused = isFocused,
|
isFocused = isFocused,
|
||||||
onFocus = { isFocused = true }
|
onFocus = { isFocused = true },
|
||||||
|
onDelete = { searchQuery = searchQuery.dropLast(1) }
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
@ -178,86 +185,45 @@ fun ReprintAnyTransactionScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun SearchInputBox(
|
|
||||||
query: String,
|
|
||||||
isFocused: Boolean,
|
|
||||||
onFocus: () -> Unit,
|
|
||||||
) {
|
|
||||||
Card(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.clickable(onClick = onFocus),
|
|
||||||
colors = CardDefaults.cardColors(containerColor = Color.White),
|
|
||||||
shape = RoundedCornerShape(12.dp),
|
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = if (isFocused) 6.dp else 2.dp)
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp, vertical = 14.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
|
||||||
) {
|
|
||||||
Column(modifier = Modifier.weight(1f)) {
|
|
||||||
Text(
|
|
||||||
text = if (isFocused) "Trace or RRN" else "Tap to search by Trace or RRN",
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = if (isFocused) Color.LegacyRed else Color.Gray
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
Text(
|
|
||||||
text = query.ifEmpty { "_" },
|
|
||||||
color = Color.LegacyRed,
|
|
||||||
style = MaterialTheme.typography.headlineSmall.copy(
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
letterSpacing = 2.sp
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.isNotEmpty()) {
|
@Preview(showBackground = true)
|
||||||
Card(
|
|
||||||
shape = RoundedCornerShape(18.dp),
|
|
||||||
colors = CardDefaults.cardColors(containerColor = Color.White),
|
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
|
|
||||||
modifier = Modifier
|
|
||||||
.shadow(2.dp, RoundedCornerShape(18.dp))
|
|
||||||
.clickable { }
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.AutoMirrored.Rounded.Backspace,
|
|
||||||
contentDescription = "Delete",
|
|
||||||
tint = Color.LegacyRed,
|
|
||||||
modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@P2Preview
|
|
||||||
@P3Preview
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ReprintAnyTransactionScreenPreview() {
|
private fun ReprintAnyTransactionScreenPreview() {
|
||||||
MOBPOSTheme {
|
MOBPOSTheme {
|
||||||
Box(modifier = Modifier.height(600.dp)) {
|
ReprintAnyTransactionContent(
|
||||||
Card(
|
allTransactions = listOf(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
PayDetail().apply {
|
||||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
transDate = "21/09/26"
|
||||||
) {
|
transTime = "14:04:15"
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
merchantName = "UTS Merchant"
|
||||||
Text(
|
merchantNo = "100089476209176"
|
||||||
text = "SALE",
|
terminalNo = "10420257"
|
||||||
color = Color.LegacyRed,
|
voucherNo = "000001"
|
||||||
style = MaterialTheme.typography.titleSmall
|
referNo = "123456789012"
|
||||||
|
approvalCode = "123456"
|
||||||
|
transType = "SALE"
|
||||||
|
amount = 1500000L
|
||||||
|
accountType = "MPU"
|
||||||
|
cardNo = "9503036867315548"
|
||||||
|
},
|
||||||
|
PayDetail().apply {
|
||||||
|
transDate = "21/09/26"
|
||||||
|
transTime = "15:20:30"
|
||||||
|
merchantName = "UTS Merchant"
|
||||||
|
merchantNo = "100089476209176"
|
||||||
|
terminalNo = "10420257"
|
||||||
|
voucherNo = "000002"
|
||||||
|
referNo = "123456789013"
|
||||||
|
approvalCode = "654321"
|
||||||
|
transType = "SALE"
|
||||||
|
amount = 250000L
|
||||||
|
accountType = "MPU"
|
||||||
|
cardNo = "9503036867319999"
|
||||||
|
}
|
||||||
|
),
|
||||||
|
hostType = HostType.MPU,
|
||||||
|
onBack = {},
|
||||||
|
onReprintTransaction = {}
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
Text("Trace 000001", style = MaterialTheme.typography.bodySmall)
|
|
||||||
Text("RRN 123456789012", style = MaterialTheme.typography.bodySmall, color = Color.Gray)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,19 @@ package com.mob.utsmyanmar.ui.history_functions
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
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.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -15,16 +24,34 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||||
|
import com.mob.utsmyanmar.ui.preview.P2Preview
|
||||||
|
import com.mob.utsmyanmar.ui.preview.P3Preview
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
|
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
|
||||||
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReviewDetailScreen(
|
fun ReviewDetailScreen(
|
||||||
viewModel: HistoryViewModel,
|
viewModel: HistoryViewModel,
|
||||||
trace: String,
|
trace: String,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
|
onReprint: ((PayDetail) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val transaction by viewModel.searchTransaction(trace).observeAsState()
|
val transaction by viewModel.searchTransaction(trace).observeAsState()
|
||||||
|
|
||||||
|
ReviewDetailContent(
|
||||||
|
transaction = transaction,
|
||||||
|
onBack = onBack,
|
||||||
|
onReprint = onReprint
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReviewDetailContent(
|
||||||
|
transaction: PayDetail?,
|
||||||
|
onBack: () -> Unit,
|
||||||
|
onReprint: ((PayDetail) -> Unit)? = null,
|
||||||
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
containerColor = Color.IvoryBeige,
|
containerColor = Color.IvoryBeige,
|
||||||
topBar = {
|
topBar = {
|
||||||
@ -40,9 +67,28 @@ fun ReviewDetailScreen(
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
transaction?.let { payDetail ->
|
transaction?.let { payDetail ->
|
||||||
HistoryTransactionDetailCard(payDetail)
|
HistoryTransactionDetailCard(payDetail)
|
||||||
|
|
||||||
|
if (onReprint != null && isValidForReprint(payDetail)) {
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Button(
|
||||||
|
onClick = { onReprint(prepareReprintPayDetail(payDetail)) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(48.dp),
|
||||||
|
shape = RoundedCornerShape(8.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(containerColor = Color.LegacyRed)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Reprint",
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
} ?: Box(
|
} ?: Box(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
@ -52,3 +98,68 @@ fun ReviewDetailScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@P2Preview
|
||||||
|
@P3Preview
|
||||||
|
@Composable
|
||||||
|
private fun ReviewDetailScreenPreview() {
|
||||||
|
MOBPOSTheme {
|
||||||
|
ReviewDetailContent(
|
||||||
|
transaction = PayDetail().apply {
|
||||||
|
transDate = "21/09/26"
|
||||||
|
transTime = "14:04:15"
|
||||||
|
merchantName = "UTS Merchant"
|
||||||
|
merchantNo = "100089476209176"
|
||||||
|
terminalNo = "10420257"
|
||||||
|
voucherNo = "000001"
|
||||||
|
referNo = "123456789012"
|
||||||
|
approvalCode = "123456"
|
||||||
|
transType = "SALE"
|
||||||
|
amount = 1500000L
|
||||||
|
accountType = "MPU"
|
||||||
|
cardNo = "9503036867315548"
|
||||||
|
tradeAnswerCode = "00"
|
||||||
|
},
|
||||||
|
onBack = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@P2Preview
|
||||||
|
@P3Preview
|
||||||
|
@Composable
|
||||||
|
private fun ReviewDetailScreenWithReprintPreview() {
|
||||||
|
MOBPOSTheme {
|
||||||
|
ReviewDetailContent(
|
||||||
|
transaction = PayDetail().apply {
|
||||||
|
transDate = "21/09/26"
|
||||||
|
transTime = "14:04:15"
|
||||||
|
merchantName = "UTS Merchant"
|
||||||
|
merchantNo = "100089476209176"
|
||||||
|
terminalNo = "10420257"
|
||||||
|
voucherNo = "000001"
|
||||||
|
referNo = "123456789012"
|
||||||
|
approvalCode = "123456"
|
||||||
|
transType = "SALE"
|
||||||
|
amount = 1500000L
|
||||||
|
accountType = "MPU"
|
||||||
|
cardNo = "9503036867315548"
|
||||||
|
tradeAnswerCode = "00"
|
||||||
|
},
|
||||||
|
onBack = {},
|
||||||
|
onReprint = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@P2Preview
|
||||||
|
@P3Preview
|
||||||
|
@Composable
|
||||||
|
private fun ReviewDetailScreenNotFoundPreview() {
|
||||||
|
MOBPOSTheme {
|
||||||
|
ReviewDetailContent(
|
||||||
|
transaction = null,
|
||||||
|
onBack = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,18 +1,20 @@
|
|||||||
package com.mob.utsmyanmar.ui.history_functions
|
package com.mob.utsmyanmar.ui.history_functions
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.slideInVertically
|
||||||
|
import androidx.compose.animation.slideOutVertically
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.CardDefaults
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -22,16 +24,16 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.mob.utsmyanmar.ui.components.NumericKeypad
|
||||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||||
|
import com.mob.utsmyanmar.ui.preview.P2Preview
|
||||||
|
import com.mob.utsmyanmar.ui.preview.P3Preview
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
|
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
|
||||||
import com.utsmyanmar.paylibs.model.PayDetail
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -40,7 +42,6 @@ fun ReviewTraceScreen(
|
|||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onNavigateReviewDetail: (String) -> Unit,
|
onNavigateReviewDetail: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
var traceNumber by remember { mutableStateOf("") }
|
|
||||||
var searchedTrace by remember { mutableStateOf("") }
|
var searchedTrace by remember { mutableStateOf("") }
|
||||||
var lastNavigatedTrace by remember { mutableStateOf<String?>(null) }
|
var lastNavigatedTrace by remember { mutableStateOf<String?>(null) }
|
||||||
|
|
||||||
@ -61,6 +62,24 @@ fun ReviewTraceScreen(
|
|||||||
onNavigateReviewDetail(matchedTrace)
|
onNavigateReviewDetail(matchedTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReviewTraceContent(
|
||||||
|
searchedTrace = searchedTrace,
|
||||||
|
transactionFound = transaction != null,
|
||||||
|
onBack = onBack,
|
||||||
|
onSearch = { query -> searchedTrace = query }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReviewTraceContent(
|
||||||
|
searchedTrace: String,
|
||||||
|
transactionFound: Boolean,
|
||||||
|
onBack: () -> Unit,
|
||||||
|
onSearch: (String) -> Unit,
|
||||||
|
) {
|
||||||
|
var traceNumber by remember { mutableStateOf("") }
|
||||||
|
var isFocused by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
containerColor = Color.IvoryBeige,
|
containerColor = Color.IvoryBeige,
|
||||||
topBar = {
|
topBar = {
|
||||||
@ -78,12 +97,12 @@ fun ReviewTraceScreen(
|
|||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = if (searchedTrace.isNotBlank() && transaction == null) {
|
text = if (searchedTrace.isNotBlank() && !transactionFound) {
|
||||||
"No transaction found for trace $searchedTrace."
|
"No transaction found for trace $searchedTrace."
|
||||||
} else {
|
} else {
|
||||||
"Input trace number to review transaction."
|
"Input trace number to review transaction."
|
||||||
},
|
},
|
||||||
color = if (searchedTrace.isNotBlank() && transaction == null) {
|
color = if (searchedTrace.isNotBlank() && !transactionFound) {
|
||||||
Color.LegacyRed
|
Color.LegacyRed
|
||||||
} else {
|
} else {
|
||||||
Color.Black
|
Color.Black
|
||||||
@ -93,49 +112,66 @@ fun ReviewTraceScreen(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
Card(
|
SearchInputBox(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
query = traceNumber,
|
||||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
isFocused = isFocused,
|
||||||
) {
|
onFocus = { isFocused = true },
|
||||||
Text(
|
onDelete = { traceNumber = traceNumber.dropLast(1) }
|
||||||
text = traceNumber.padStart(6, '0').ifEmpty { "000000" },
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(24.dp),
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
style = MaterialTheme.typography.displayMedium.copy(fontSize = 28.sp)
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
HistoryNumericKeypad(
|
AnimatedVisibility(
|
||||||
onDigit = { digit ->
|
visible = isFocused,
|
||||||
if (traceNumber.length < 6) traceNumber += digit
|
enter = slideInVertically(initialOffsetY = { it }),
|
||||||
},
|
exit = slideOutVertically(targetOffsetY = { it })
|
||||||
onBackspace = {
|
) {
|
||||||
if (traceNumber.isNotEmpty()) {
|
NumericKeypad(
|
||||||
traceNumber = traceNumber.dropLast(1)
|
keys = searchKeys,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(280.dp)
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
onKeyClick = { key ->
|
||||||
|
when (key) {
|
||||||
|
"C" -> traceNumber = ""
|
||||||
|
"\u232B" -> traceNumber = traceNumber.dropLast(1)
|
||||||
|
else -> if (traceNumber.length < 12) traceNumber += key
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
onClear = { traceNumber = "" }
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { searchedTrace = traceNumber.padStart(6, '0') },
|
onClick = { onSearch(traceNumber.trim()) },
|
||||||
enabled = traceNumber.isNotBlank(),
|
enabled = traceNumber.isNotBlank(),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(56.dp),
|
.height(56.dp),
|
||||||
|
shape = RoundedCornerShape(8.dp),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Color.LegacyRed,
|
containerColor = Color.LegacyRed,
|
||||||
contentColor = Color.White
|
contentColor = Color.White
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text("Search")
|
Text("Search", style = MaterialTheme.typography.titleMedium)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@P2Preview
|
||||||
|
@P3Preview
|
||||||
|
@Composable
|
||||||
|
private fun ReviewTraceScreenPreview() {
|
||||||
|
MOBPOSTheme {
|
||||||
|
ReviewTraceContent(
|
||||||
|
searchedTrace = "",
|
||||||
|
transactionFound = false,
|
||||||
|
onBack = {},
|
||||||
|
onSearch = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -52,7 +52,7 @@ fun SelectHostScreen(
|
|||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
HostButton("MPU") { onSelectHost(HostType.MPU) }
|
HostButton("MPU / JCB / UPI") { onSelectHost(HostType.MPU) }
|
||||||
HostButton("Visa / Master") {
|
HostButton("Visa / Master") {
|
||||||
if (SystemParamsOperation.getInstance().isEmvEnabled) {
|
if (SystemParamsOperation.getInstance().isEmvEnabled) {
|
||||||
onSelectHost(HostType.VISA_MASTER)
|
onSelectHost(HostType.VISA_MASTER)
|
||||||
|
|||||||
@ -669,8 +669,22 @@ fun AppNavGraph(
|
|||||||
},
|
},
|
||||||
onNavigateInputAmount = { navController.popBackStack(Routes.Amount.route, false) },
|
onNavigateInputAmount = { navController.popBackStack(Routes.Amount.route, false) },
|
||||||
onNavigateProcessing = {},
|
onNavigateProcessing = {},
|
||||||
onNavigateEmvTransaction = {},
|
onNavigateEmvTransaction = {
|
||||||
onNavigateError = {},
|
navController.navigate(Routes.Processing.route) {
|
||||||
|
popUpTo(Routes.ProcessingCard.route) {
|
||||||
|
inclusive = true
|
||||||
|
}
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onNavigateError = { message ->
|
||||||
|
navController.navigate(Routes.TransactionError.createRoute(false, message)) {
|
||||||
|
popUpTo(Routes.ProcessingCard.route) {
|
||||||
|
inclusive = true
|
||||||
|
}
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
onBack = { navController.popBackStack() },
|
onBack = { navController.popBackStack() },
|
||||||
onShowDecline = {}
|
onShowDecline = {}
|
||||||
)
|
)
|
||||||
@ -761,6 +775,7 @@ fun AppNavGraph(
|
|||||||
sharedViewModel = sharedViewModel,
|
sharedViewModel = sharedViewModel,
|
||||||
transProcessViewModel = transProcessViewModel,
|
transProcessViewModel = transProcessViewModel,
|
||||||
settlementViewModel = settlementViewModel,
|
settlementViewModel = settlementViewModel,
|
||||||
|
emvTransactionViewModel = hiltViewModel(activity),
|
||||||
onTransactionFinished = {
|
onTransactionFinished = {
|
||||||
tmsSetupViewModel.downloadConfigs(dashboardViewModel::refreshLastSyncTime)
|
tmsSetupViewModel.downloadConfigs(dashboardViewModel::refreshLastSyncTime)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import com.utsmyanmar.paylibs.model.PayDetail
|
|||||||
import com.utsmyanmar.paylibs.model.TradeData
|
import com.utsmyanmar.paylibs.model.TradeData
|
||||||
import com.utsmyanmar.paylibs.model.enums.TransCVM
|
import com.utsmyanmar.paylibs.model.enums.TransCVM
|
||||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
|
||||||
import com.utsmyanmar.paylibs.utils.enums.TransMenu
|
import com.utsmyanmar.paylibs.utils.enums.TransMenu
|
||||||
import com.utsmyanmar.paylibs.utils.params.Params
|
import com.utsmyanmar.paylibs.utils.params.Params
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
@ -250,7 +249,10 @@ class ProcessingCardViewModel(
|
|||||||
emvTransactionViewModel.transType.value =
|
emvTransactionViewModel.transType.value =
|
||||||
sharedViewModel.transactionsType.value
|
sharedViewModel.transactionsType.value
|
||||||
|
|
||||||
if (SystemParamsOperation.getInstance().isEmvEnabled) {
|
if (
|
||||||
|
// SystemParamsOperation.getInstance().isEmvEnabled
|
||||||
|
true
|
||||||
|
) {
|
||||||
prepareEmvTransaction()
|
prepareEmvTransaction()
|
||||||
sendUiEvent(ProcessingCardUiEvent.NavigateToEmvTransaction)
|
sendUiEvent(ProcessingCardUiEvent.NavigateToEmvTransaction)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -4,11 +4,13 @@ import android.R
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.mob.utsmyanmar.model.TransResultStatus
|
import com.mob.utsmyanmar.model.TransResultStatus
|
||||||
import com.mob.utsmyanmar.model.TransactionStatus
|
import com.mob.utsmyanmar.model.TransactionStatus
|
||||||
import com.mob.utsmyanmar.ui.settlement.SettlementViewModel
|
import com.mob.utsmyanmar.ui.settlement.SettlementViewModel
|
||||||
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||||
|
import com.mob.utsmyanmar.viewmodel.EmvTransactionProcessViewModel
|
||||||
import com.mob.utsmyanmar.viewmodel.TransProcessViewModel
|
import com.mob.utsmyanmar.viewmodel.TransProcessViewModel
|
||||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||||
|
|
||||||
@ -19,6 +21,7 @@ fun ProcessingRoute(
|
|||||||
sharedViewModel: SharedViewModel,
|
sharedViewModel: SharedViewModel,
|
||||||
transProcessViewModel: TransProcessViewModel,
|
transProcessViewModel: TransProcessViewModel,
|
||||||
settlementViewModel: SettlementViewModel,
|
settlementViewModel: SettlementViewModel,
|
||||||
|
emvTransactionViewModel: EmvTransactionProcessViewModel,
|
||||||
onNavigateTransactionResult: () -> Unit,
|
onNavigateTransactionResult: () -> Unit,
|
||||||
onNavigateSignature: () -> Unit,
|
onNavigateSignature: () -> Unit,
|
||||||
onNavigateError: (Boolean, String) -> Unit,
|
onNavigateError: (Boolean, String) -> Unit,
|
||||||
@ -26,12 +29,47 @@ fun ProcessingRoute(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
val transStatus by transProcessViewModel.transResultStatus.collectAsStateWithLifecycle()
|
val transStatus by transProcessViewModel.transResultStatus.collectAsStateWithLifecycle()
|
||||||
|
val emvStatus by emvTransactionViewModel.getTransStatus().observeAsState()
|
||||||
|
|
||||||
val state by transProcessViewModel.state.collectAsStateWithLifecycle()
|
val state by transProcessViewModel.state.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
val settlementStatus by settlementViewModel.uiState.collectAsStateWithLifecycle()
|
val settlementStatus by settlementViewModel.uiState.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) {
|
if (sharedViewModel.isEmvTrans().value == true) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
emvTransactionViewModel.startProcess()
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(emvStatus) {
|
||||||
|
when (emvStatus) {
|
||||||
|
TransResultStatus.SUCCESS,
|
||||||
|
TransResultStatus.OFFLINE_SUCCESS -> {
|
||||||
|
onTransactionFinished()
|
||||||
|
sharedViewModel.payDetail.value = emvTransactionViewModel.payDetailResult.value
|
||||||
|
onNavigateTransactionResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
TransResultStatus.FAIL,
|
||||||
|
TransResultStatus.OFFLINE_FAILURE -> {
|
||||||
|
onTransactionFinished()
|
||||||
|
sharedViewModel.payDetail.value = emvTransactionViewModel.payDetailResult.value
|
||||||
|
onNavigateTransactionResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
TransResultStatus.NETWORK_ERROR,
|
||||||
|
TransResultStatus.ERROR -> {
|
||||||
|
onTransactionFinished()
|
||||||
|
onNavigateError(
|
||||||
|
false,
|
||||||
|
emvTransactionViewModel.errorCodeMsg.value
|
||||||
|
?: "Something went wrong. Please try again."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) {
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
settlementViewModel.startSettlementProcess()
|
settlementViewModel.startSettlementProcess()
|
||||||
}
|
}
|
||||||
@ -98,7 +136,9 @@ fun ProcessingRoute(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) {
|
if (sharedViewModel.isEmvTrans().value == true) {
|
||||||
|
ProcessingScreen(state)
|
||||||
|
} else if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) {
|
||||||
ProcessingScreen(settlementStatus.processingState)
|
ProcessingScreen(settlementStatus.processingState)
|
||||||
} else {
|
} else {
|
||||||
ProcessingScreen(state)
|
ProcessingScreen(state)
|
||||||
|
|||||||
@ -25,10 +25,14 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||||
|
import com.mob.utsmyanmar.ui.history_functions.displayAmountWithSign
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
|
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
|
||||||
|
import com.mob.utsmyanmar.utils.convertDateString
|
||||||
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||||
import com.utsmyanmar.paylibs.model.PayDetail
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||||
@ -42,6 +46,22 @@ fun SettlementScreen(
|
|||||||
autoStartSettlement: Boolean = false
|
autoStartSettlement: Boolean = false
|
||||||
) {
|
) {
|
||||||
val records by settlementViewMode.getSettlementPOS().observeAsState(emptyList())
|
val records by settlementViewMode.getSettlementPOS().observeAsState(emptyList())
|
||||||
|
|
||||||
|
SettlementContent(
|
||||||
|
records = records,
|
||||||
|
onBack = onBack,
|
||||||
|
onStartSettlement = onStartSettlement,
|
||||||
|
autoStartSettlement = autoStartSettlement
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SettlementContent(
|
||||||
|
records: List<PayDetail>,
|
||||||
|
onBack: () -> Unit,
|
||||||
|
onStartSettlement: () -> Unit,
|
||||||
|
autoStartSettlement: Boolean = false
|
||||||
|
) {
|
||||||
val totalAmount = records.sumOf { it.amount }
|
val totalAmount = records.sumOf { it.amount }
|
||||||
|
|
||||||
LaunchedEffect(autoStartSettlement, records) {
|
LaunchedEffect(autoStartSettlement, records) {
|
||||||
@ -116,7 +136,7 @@ fun SettlementScreen(
|
|||||||
verticalArrangement = Arrangement.spacedBy(0.dp)
|
verticalArrangement = Arrangement.spacedBy(0.dp)
|
||||||
) {
|
) {
|
||||||
items(records) { record ->
|
items(records) { record ->
|
||||||
SettlementRecordRow(record = record)
|
SettlementRecordRow(payDetail = record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,40 +184,87 @@ private fun SummaryRow(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SettlementRecordRow(record: PayDetail) {
|
private fun SettlementRecordRow(payDetail: PayDetail) {
|
||||||
Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)) {
|
Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)) {
|
||||||
Row(
|
Spacer(Modifier.height(4.dp))
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
text = record.transType
|
text = payDetail.transType
|
||||||
|
.orEmpty()
|
||||||
.ifBlank { "UNKNOWN" }
|
.ifBlank { "UNKNOWN" }
|
||||||
.replace("CASH_OUT", "CASH_ADV", ignoreCase = true),
|
.replace("CASH_OUT", "CASH_ADV", ignoreCase = true),
|
||||||
color = Color.LegacyRed,
|
color = Color.LegacyRed,
|
||||||
style = MaterialTheme.typography.titleSmall
|
style = MaterialTheme.typography.titleSmall
|
||||||
)
|
)
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = POSUtil.getInstance().getDecimalAmountSeparatorFormat(record.amount),
|
text = "Date & Time",
|
||||||
color = Color.Black,
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "${convertDateString(payDetail.transDate.orEmpty())} ${payDetail.transTime.orEmpty()}".trim().ifBlank { "-" },
|
||||||
style = MaterialTheme.typography.titleSmall
|
style = MaterialTheme.typography.titleSmall
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "Trace ${record.voucherNo.ifBlank { "-" }}",
|
text = "Amount",
|
||||||
color = Color.Black,
|
style = MaterialTheme.typography.titleSmall
|
||||||
style = MaterialTheme.typography.bodySmall
|
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = "Card ${maskCardNumber(record.cardNo)}",
|
text = displayAmountWithSign(payDetail),
|
||||||
color = Color.Gray,
|
style = MaterialTheme.typography.titleSmall
|
||||||
style = MaterialTheme.typography.bodySmall
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Trace No",
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = payDetail.voucherNo.orEmpty().ifBlank { "-" },
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Reference No",
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = payDetail.referNo.orEmpty().ifBlank { "-" },
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Approval Code",
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = payDetail.approvalCode.orEmpty().ifBlank { "-" },
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(Modifier.height(4.dp))
|
||||||
HorizontalDivider(color = Color.Gray.copy(alpha = 0.25f))
|
HorizontalDivider(color = Color.Gray.copy(alpha = 0.25f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,3 +276,29 @@ private fun maskCardNumber(cardNo: String?): String {
|
|||||||
val stars = "*".repeat(pan.length - 8)
|
val stars = "*".repeat(pan.length - 8)
|
||||||
return pan.take(4) + stars + pan.takeLast(4)
|
return pan.take(4) + stars + pan.takeLast(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun SettlementScreenPreview() {
|
||||||
|
val sampleRecords = listOf(
|
||||||
|
PayDetail().apply {
|
||||||
|
transType = "SALE"
|
||||||
|
amount = 150000L
|
||||||
|
voucherNo = "000001"
|
||||||
|
cardNo = "9503036867315548"
|
||||||
|
},
|
||||||
|
PayDetail().apply {
|
||||||
|
transType = "CASH_OUT"
|
||||||
|
amount = 50000L
|
||||||
|
voucherNo = "000002"
|
||||||
|
cardNo = "9503036867311234"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
MOBPOSTheme {
|
||||||
|
SettlementContent(
|
||||||
|
records = sampleRecords,
|
||||||
|
onBack = {},
|
||||||
|
onStartSettlement = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ fun String?.maskCardNumber(): String {
|
|||||||
return maskedPan.toString()
|
return maskedPan.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertDateString(dateStr: String): String {
|
fun convertDateString(dateStr: String?): String {
|
||||||
|
if (dateStr.isNullOrEmpty()) return ""
|
||||||
return dateStr.replace(Regex("/(\\d{2})$"), "/20$1")
|
return dateStr.replace(Regex("/(\\d{2})$"), "/20$1")
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ class TMSSetupsImpl : TMSSetups {
|
|||||||
ops.merchantName = m.name
|
ops.merchantName = m.name
|
||||||
ops.merchantAddress = m.address
|
ops.merchantAddress = m.address
|
||||||
ops.merchantPhoneNo = m.phone
|
ops.merchantPhoneNo = m.phone
|
||||||
ops.merchantMobileNo = m.mobile_phone
|
ops.merchantMobileNo = m.mobilePhone.orEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
siriusResponse.address.takeIf { it.isNotEmpty() }?.let { ops.merchantAddress = it }
|
siriusResponse.address.takeIf { it.isNotEmpty() }?.let { ops.merchantAddress = it }
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.utsmyanmar.baselib.network.model.sirius;
|
package com.utsmyanmar.baselib.network.model.sirius;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
public class SiriusMerchant {
|
public class SiriusMerchant {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
@ -16,7 +18,11 @@ public class SiriusMerchant {
|
|||||||
|
|
||||||
private String mobile;
|
private String mobile;
|
||||||
|
|
||||||
private String mobile_phone;
|
@SerializedName(value = "mobilePhone", alternate = {"mobile_phone"})
|
||||||
|
private String mobilePhone;
|
||||||
|
|
||||||
|
public SiriusMerchant() {
|
||||||
|
}
|
||||||
|
|
||||||
public SiriusMerchant(String id, String name, String description, String address,String address2,String phone,String mobile) {
|
public SiriusMerchant(String id, String name, String description, String address,String address2,String phone,String mobile) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -28,6 +34,17 @@ public class SiriusMerchant {
|
|||||||
this.mobile = mobile;
|
this.mobile = mobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SiriusMerchant(String id, String name, String description, String address, String address2, String phone, String mobile, String mobilePhone) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.address = address;
|
||||||
|
this.address2 = address2;
|
||||||
|
this.phone = phone;
|
||||||
|
this.mobile = mobile;
|
||||||
|
this.mobilePhone = mobilePhone;
|
||||||
|
}
|
||||||
|
|
||||||
public void setAddress2(String address2) {
|
public void setAddress2(String address2) {
|
||||||
this.address2 = address2;
|
this.address2 = address2;
|
||||||
}
|
}
|
||||||
@ -52,12 +69,20 @@ public class SiriusMerchant {
|
|||||||
return mobile;
|
return mobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMobilePhone() {
|
||||||
|
return mobilePhone != null ? mobilePhone : mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMobilePhone(String mobilePhone) {
|
||||||
|
this.mobilePhone = mobilePhone;
|
||||||
|
}
|
||||||
|
|
||||||
public String getMobile_phone() {
|
public String getMobile_phone() {
|
||||||
return mobile_phone;
|
return getMobilePhone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMobile_phone(String mobile_phone) {
|
public void setMobile_phone(String mobile_phone) {
|
||||||
this.mobile_phone = mobile_phone;
|
this.mobilePhone = mobile_phone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(String id) {
|
public void setId(String id) {
|
||||||
|
|||||||
@ -88,23 +88,33 @@ public class BaseErrorCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getCode(String code) {
|
public static String getCode(String code) {
|
||||||
if (instance == null) instance = new BaseErrorCode();
|
if (instance == null || (instance.errorCode.isEmpty() && PayLibsUtils.getInstance().context != null)) {
|
||||||
|
instance = new BaseErrorCode();
|
||||||
|
}
|
||||||
String errorMsg = instance.errorCode.get(code);
|
String errorMsg = instance.errorCode.get(code);
|
||||||
// return (errorMsg != null ? "RESPONSE CODE"+"(" + code + ")\n ("+errorMsg+")" : getString(R.string.errorOthers));
|
// return (errorMsg != null ? "RESPONSE CODE"+"(" + code + ")\n ("+errorMsg+")" : getString(R.string.errorOthers));
|
||||||
if(code.length() == 2) {
|
if(code.length() == 2) {
|
||||||
return (errorMsg != null ? errorMsg : getString(R.string.errorOthers));
|
if (errorMsg != null) return errorMsg;
|
||||||
|
String defaultError = getString(R.string.errorOthers);
|
||||||
|
return defaultError != null ? defaultError : ("00".equals(code) ? "Approved" : "Others");
|
||||||
} else if(code.isEmpty()) {
|
} else if(code.isEmpty()) {
|
||||||
return "NO RESPONSE";
|
return "NO RESPONSE";
|
||||||
} else {
|
} else {
|
||||||
return (errorMsg != null ? code + " - "+errorMsg : getString(R.string.errorOthers));
|
if (errorMsg != null) return code + " - "+errorMsg;
|
||||||
|
String defaultError = getString(R.string.errorOthers);
|
||||||
|
return defaultError != null ? code + " - " + defaultError : code + " - Others";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getErrorMessage(String code) {
|
public static String getErrorMessage(String code) {
|
||||||
if (instance == null) instance = new BaseErrorCode();
|
if (instance == null || (instance.errorCode.isEmpty() && PayLibsUtils.getInstance().context != null)) {
|
||||||
|
instance = new BaseErrorCode();
|
||||||
|
}
|
||||||
String errorMsg = instance.errorCode.get(code);
|
String errorMsg = instance.errorCode.get(code);
|
||||||
return (errorMsg != null ?" "+ errorMsg+" " :getString(R.string.errorOthers));
|
if (errorMsg != null) return " " + errorMsg + " ";
|
||||||
|
String defaultError = getString(R.string.errorOthers);
|
||||||
|
return " " + (defaultError != null ? defaultError : "Others") + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BaseErrorCode instance;
|
private static BaseErrorCode instance;
|
||||||
@ -117,14 +127,21 @@ public class BaseErrorCode {
|
|||||||
if (KeyValueSet == null) return;
|
if (KeyValueSet == null) return;
|
||||||
int size = KeyValueSet.length;
|
int size = KeyValueSet.length;
|
||||||
if (size % 2 == 0)
|
if (size % 2 == 0)
|
||||||
for (int i = 0; i < size; i += 2)
|
for (int i = 0; i < size; i += 2) {
|
||||||
errorCode.put((String) KeyValueSet[i],getString((Integer)KeyValueSet[i + 1]));
|
String val = getString((Integer)KeyValueSet[i + 1]);
|
||||||
|
if (val != null) {
|
||||||
|
errorCode.put((String) KeyValueSet[i], val);
|
||||||
|
}
|
||||||
|
}
|
||||||
else throw new RuntimeException("Error code key value pairs must be even numbers");
|
else throw new RuntimeException("Error code key value pairs must be even numbers");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> errorCode = new HashMap<>();
|
private Map<String, String> errorCode = new HashMap<>();
|
||||||
|
|
||||||
private static String getString(int id) {
|
private static String getString(int id) {
|
||||||
|
if (PayLibsUtils.getInstance() == null || PayLibsUtils.getInstance().context == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return PayLibsUtils.getInstance().context.getString(id);
|
return PayLibsUtils.getInstance().context.getString(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package com.utsmyanmar.paylibs.utils;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import sunmi.sunmiui.utils.LogUtil;
|
import sunmi.sunmiui.utils.LogUtil;
|
||||||
|
import com.utsmyanmar.paylibs.utils.enums.CardScheme;
|
||||||
|
|
||||||
public class CardSchemeUtils {
|
public class CardSchemeUtils {
|
||||||
private static final String TAG = "CardSchemeUtil";
|
private static final String TAG = "CardSchemeUtil";
|
||||||
@ -25,19 +26,8 @@ public class CardSchemeUtils {
|
|||||||
} else if ("A000000524".equals(group)) {
|
} else if ("A000000524".equals(group)) {
|
||||||
accountType = AccountType.RPC.getValue();
|
accountType = AccountType.RPC.getValue();
|
||||||
} else if ("A000000333".equals(group)) {
|
} else if ("A000000333".equals(group)) {
|
||||||
if ("A000000333010101".equals(aid)) {
|
// Keep the scheme value used by host routing and receipt logic.
|
||||||
|
accountType = CardScheme.UPI.name;
|
||||||
accountType = AccountType.DD.getValue();
|
|
||||||
} else if ("A000000333010102".equals(aid)) {
|
|
||||||
|
|
||||||
accountType = AccountType.CC.getValue();
|
|
||||||
} else if ("A000000333010103".equals(aid)) {
|
|
||||||
|
|
||||||
accountType = AccountType.SCC.getValue();
|
|
||||||
} else if ("A000000333010101".equals(aid)) {
|
|
||||||
|
|
||||||
accountType = AccountType.EC.getValue();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
LogUtil.d(TAG, "Card accountType = " + accountType);
|
LogUtil.d(TAG, "Card accountType = " + accountType);
|
||||||
return accountType;
|
return accountType;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user