added history functions
This commit is contained in:
parent
f827e75b1e
commit
1a7e4c2020
@ -107,6 +107,7 @@ fun DashboardScreen2(
|
||||
onNavigateSettlement: () -> Unit = {},
|
||||
onNavigateVersion: () -> Unit = {},
|
||||
onNavigateFunctions: () -> Unit = {},
|
||||
onNavigateHistory: () -> Unit = {},
|
||||
onNavigateAction: (String) -> Unit = {},
|
||||
onNavigateNotifications: () -> Unit = {},
|
||||
dashboardUiState: DashboardUiState = DashboardUiState(),
|
||||
@ -455,6 +456,7 @@ fun DashboardScreen2(
|
||||
onNavigateAmount = onNavigateAmount,
|
||||
onNavigateSignOn = onNavigateSignOn,
|
||||
onNavigateSettlement = onNavigateSettlement,
|
||||
onNavigateHistory = onNavigateHistory,
|
||||
onNavigateAction = onNavigateAction
|
||||
),
|
||||
modifier = Modifier
|
||||
@ -675,6 +677,7 @@ private fun buildMenuItems(
|
||||
onNavigateAmount: (String) -> Unit,
|
||||
onNavigateSignOn: () -> Unit,
|
||||
onNavigateSettlement: () -> Unit,
|
||||
onNavigateHistory: () -> Unit,
|
||||
onNavigateAction: (String) -> Unit
|
||||
): List<DashboardMenuItem> = listOf(
|
||||
DashboardMenuItem(
|
||||
@ -705,7 +708,7 @@ private fun buildMenuItems(
|
||||
modifier = Modifier.size(32.dp),
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
}) { },
|
||||
}) { onNavigateHistory() },
|
||||
DashboardMenuItem(
|
||||
"Sign On",
|
||||
{
|
||||
|
||||
@ -0,0 +1,87 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.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.unit.dp
|
||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||
import com.mob.utsmyanmar.ui.theme.Color
|
||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||
|
||||
@Composable
|
||||
fun BatchTotalScreen(
|
||||
viewModel: HistoryViewModel,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
val batchNo = SystemParamsOperation.getInstance().currentBatchNum
|
||||
val records by viewModel.getReviewBatchTransaction(batchNo).observeAsState(emptyList())
|
||||
val totalAmount = records.sumOf { detailReportSignedAmount(it) }
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Batch Total",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
SummaryLine("Batch No", batchNo)
|
||||
SummaryLine("Record Count", records.size.toString())
|
||||
SummaryLine("Total Amount", POSUtil.getInstance().formatAmount(totalAmount))
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
if (records.isEmpty()) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text("No batch records found.", color = Color.Gray)
|
||||
}
|
||||
} else {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
items(records, key = { "${it.voucherNo}_${it.PID}" }) { record ->
|
||||
HistoryTransactionCard(record, onClick = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
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.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||
import com.mob.utsmyanmar.ui.theme.Color
|
||||
import com.utsmyanmar.paylibs.print.PrintHelper
|
||||
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt
|
||||
import com.utsmyanmar.paylibs.print.printx.PrintXStatus
|
||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||
import com.utsmyanmar.paylibs.utils.enums.HostType
|
||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||
import com.utsmyanmar.paylibs.utils.params.Params
|
||||
|
||||
@Composable
|
||||
fun DetailReportScreen(
|
||||
viewModel: HistoryViewModel,
|
||||
hostType: HostType,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val allTransactions by viewModel.getTransactionHistory().observeAsState(emptyList())
|
||||
var isPrinting by remember { mutableStateOf(false) }
|
||||
|
||||
val records = remember(allTransactions, hostType) {
|
||||
filterDetailReportTransactions(allTransactions, hostType)
|
||||
}
|
||||
val totalAmount = remember(records) {
|
||||
records.sumOf(::detailReportSignedAmount)
|
||||
}
|
||||
|
||||
fun printDetailReport() {
|
||||
if (records.isEmpty()) {
|
||||
Toast.makeText(context, "No transactions to print.", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
if (PrintHelper.getInstance().paperRollStatus() != 1) {
|
||||
Toast.makeText(context, "Paper roll not ready.", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
val tradeData = Params.newTrade(false)
|
||||
val payDetail = tradeData.payDetail
|
||||
payDetail.transType = TransactionsType.DETAIL_REPORT.name
|
||||
payDetail.transactionType = TransactionsType.DETAIL_REPORT.value
|
||||
|
||||
isPrinting = true
|
||||
PrintXReceipt.getInstance().printDetailReport(
|
||||
payDetail,
|
||||
ArrayList(records),
|
||||
hostType,
|
||||
object : PrintXStatus {
|
||||
override fun onSuccess() {
|
||||
isPrinting = false
|
||||
}
|
||||
|
||||
override fun onFailure() {
|
||||
isPrinting = false
|
||||
Toast.makeText(context, "Print failed.", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Print Detail Report",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
SummaryLine("Host", hostTypeLabel(hostType))
|
||||
SummaryLine("Card Type", hostTypeLabel(hostType))
|
||||
SummaryLine("Transaction Count", records.size.toString())
|
||||
SummaryLine("Total Amount", POSUtil.getInstance().formatAmount(totalAmount))
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
if (records.isEmpty()) {
|
||||
Box(
|
||||
modifier = Modifier.weight(1f),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text("No transactions available.", color = Color.Gray)
|
||||
}
|
||||
} else {
|
||||
LazyColumn(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
items(records, key = { "${it.voucherNo}_${it.PID}" }) { record ->
|
||||
HistoryTransactionCard(record, onClick = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
Button(
|
||||
onClick = ::printDetailReport,
|
||||
enabled = records.isNotEmpty() && !isPrinting,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.LegacyRed,
|
||||
contentColor = Color.White
|
||||
)
|
||||
) {
|
||||
if (isPrinting) {
|
||||
CircularProgressIndicator(color = Color.White)
|
||||
} else {
|
||||
Text("Print")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,191 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.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.rounded.Backspace
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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.theme.Color
|
||||
import com.utsmyanmar.paylibs.model.PayDetail
|
||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||
|
||||
@Composable
|
||||
internal fun HistoryTransactionCard(
|
||||
payDetail: PayDetail,
|
||||
onClick: (() -> Unit)?,
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.then(
|
||||
if (onClick != null) {
|
||||
Modifier.clickable(onClick = onClick)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = payDetail.transType.ifBlank { "UNKNOWN" },
|
||||
color = Color.LegacyRed,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
Text(
|
||||
text = POSUtil.getInstance().formatAmount(payDetail.amount),
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text("Trace ${payDetail.voucherNo.ifBlank { "-" }}", fontSize = 12.sp)
|
||||
Text("RRN ${payDetail.referNo.ifBlank { "-" }}", fontSize = 12.sp, color = Color.Gray)
|
||||
Text(
|
||||
"${payDetail.transDate} ${payDetail.transTime}",
|
||||
fontSize = 12.sp,
|
||||
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 = payDetail.transType.ifBlank { "Transaction" },
|
||||
color = Color.LegacyRed,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
SummaryLine("Trace", payDetail.voucherNo)
|
||||
SummaryLine("Amount", POSUtil.getInstance().formatAmount(payDetail.amount))
|
||||
SummaryLine("Card No", payDetail.cardNo)
|
||||
SummaryLine("Reference", payDetail.referNo)
|
||||
SummaryLine("Approval", payDetail.approvalCode.orEmpty())
|
||||
SummaryLine("Date", payDetail.tradeDate)
|
||||
SummaryLine("Time", payDetail.tradeTime)
|
||||
SummaryLine("Status", payDetail.tradeAnswerCode.orEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SummaryLine(label: String, value: String) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(label, color = Color.Gray, fontSize = 13.sp)
|
||||
Text(
|
||||
value.ifBlank { "-" },
|
||||
fontSize = 13.sp,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SummaryPickerRow(
|
||||
label: String,
|
||||
value: String,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(label, fontWeight = FontWeight.Medium)
|
||||
Text(value, color = Color.Gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun HistoryNumericKeypad(
|
||||
onDigit: (String) -> Unit,
|
||||
onBackspace: () -> Unit,
|
||||
onClear: () -> Unit,
|
||||
) {
|
||||
val rows = listOf(
|
||||
listOf("1", "2", "3"),
|
||||
listOf("4", "5", "6"),
|
||||
listOf("7", "8", "9"),
|
||||
listOf("C", "0", "⌫")
|
||||
)
|
||||
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
rows.forEach { row ->
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
row.forEach { key ->
|
||||
Button(
|
||||
onClick = {
|
||||
when (key) {
|
||||
"C" -> onClear()
|
||||
"⌫" -> onBackspace()
|
||||
else -> onDigit(key)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.height(56.dp),
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.White,
|
||||
contentColor = Color.Black
|
||||
)
|
||||
) {
|
||||
if (key == "⌫") {
|
||||
Icon(Icons.Rounded.Backspace, contentDescription = "Backspace")
|
||||
} else {
|
||||
Text(key, fontSize = 20.sp, fontWeight = FontWeight.Bold)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import com.utsmyanmar.paylibs.model.PayDetail
|
||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||
import com.utsmyanmar.paylibs.utils.enums.HostType
|
||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
enum class HistoryHostPurpose {
|
||||
REPRINT_ANY,
|
||||
LAST_SETTLEMENT,
|
||||
DETAIL_REPORT,
|
||||
SUMMARY_REPORT,
|
||||
}
|
||||
|
||||
internal fun prepareReprintPayDetail(payDetail: PayDetail): PayDetail {
|
||||
val suffix = "(REPRINT)"
|
||||
payDetail.transType = if (payDetail.transType.length >= 20) {
|
||||
"${payDetail.transType}\n$suffix"
|
||||
} else {
|
||||
payDetail.transType + suffix
|
||||
}
|
||||
return payDetail
|
||||
}
|
||||
|
||||
internal fun isValidForReprint(payDetail: PayDetail): Boolean {
|
||||
if (payDetail.transactionType == TransactionsType.SETTLEMENT.value) return false
|
||||
if (payDetail.transactionType == TransactionsType.WAVEPAY.value && payDetail.qrTransStatus != 1) {
|
||||
return false
|
||||
}
|
||||
if (payDetail.transactionType == TransactionsType.WAVEPAY_REFUND.value && payDetail.qrTransStatus != 1) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
internal fun filterReprintAnyTransactions(
|
||||
transactions: List<PayDetail>,
|
||||
hostType: HostType
|
||||
): List<PayDetail> {
|
||||
val yesterday = POSUtil.getInstance().yesterdayDate
|
||||
val dateFormat = SimpleDateFormat("dd/MM/yy", Locale.getDefault())
|
||||
|
||||
return transactions.filter { pay ->
|
||||
val transDate = parseTransDate(pay.transDate, dateFormat) ?: return@filter false
|
||||
if (yesterday.compareTo(transDate) > 0) return@filter false
|
||||
if (pay.transactionType == TransactionsType.SETTLEMENT.value) return@filter false
|
||||
if (pay.transactionType == TransactionsType.REVERSAL.value) return@filter false
|
||||
|
||||
when (hostType) {
|
||||
HostType.MPU ->
|
||||
pay.accountType == "MPU" &&
|
||||
pay.transactionType != TransactionsType.WAVEPAY.value &&
|
||||
pay.transactionType != TransactionsType.WAVEPAY_REFUND.value
|
||||
|
||||
HostType.QR ->
|
||||
(pay.transactionType == TransactionsType.WAVEPAY.value ||
|
||||
pay.transactionType == TransactionsType.WAVEPAY_REFUND.value) &&
|
||||
pay.qrTransStatus == 1
|
||||
|
||||
HostType.VISA_MASTER ->
|
||||
pay.accountType != "MPU" &&
|
||||
pay.transactionType != TransactionsType.WAVEPAY.value &&
|
||||
pay.transactionType != TransactionsType.WAVEPAY_REFUND.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun filterDetailReportTransactions(
|
||||
transactions: List<PayDetail>,
|
||||
hostType: HostType
|
||||
): List<PayDetail> {
|
||||
val yesterday = POSUtil.getInstance().yesterdayDate
|
||||
|
||||
return transactions.filter { pay ->
|
||||
if (POSUtil.getInstance().getDateByString(pay.transDate).before(yesterday)) return@filter false
|
||||
if (pay.transactionType == TransactionsType.REVERSAL.value) return@filter false
|
||||
if (pay.transactionType == TransactionsType.SETTLEMENT.value) return@filter false
|
||||
|
||||
when (hostType) {
|
||||
HostType.MPU ->
|
||||
pay.accountType == "MPU" &&
|
||||
pay.transactionType != TransactionsType.WAVEPAY_REFUND.value &&
|
||||
pay.transactionType != TransactionsType.WAVEPAY.value
|
||||
|
||||
HostType.QR ->
|
||||
(pay.transactionType == TransactionsType.WAVEPAY.value ||
|
||||
pay.transactionType == TransactionsType.WAVEPAY_REFUND.value) &&
|
||||
pay.qrTransStatus == 1
|
||||
|
||||
HostType.VISA_MASTER ->
|
||||
pay.accountType != "MPU" &&
|
||||
pay.transactionType != TransactionsType.WAVEPAY_REFUND.value &&
|
||||
pay.transactionType != TransactionsType.WAVEPAY.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun detailReportSignedAmount(payDetail: PayDetail): Long {
|
||||
val isNegative = payDetail.transactionType == TransactionsType.VOID.value ||
|
||||
payDetail.transactionType == TransactionsType.REFUND.value ||
|
||||
payDetail.transactionType == TransactionsType.WAVEPAY_REFUND.value
|
||||
return if (isNegative) -payDetail.amount else payDetail.amount
|
||||
}
|
||||
|
||||
internal fun hostTypeLabel(hostType: HostType): String = when (hostType) {
|
||||
HostType.QR -> "QR PAY"
|
||||
HostType.MPU -> "MPU"
|
||||
HostType.VISA_MASTER -> "VISA/MASTER"
|
||||
}
|
||||
|
||||
internal fun hostTypeAccountLabel(hostType: HostType): String = when (hostType) {
|
||||
HostType.QR -> "WALLET"
|
||||
HostType.MPU -> "MPU"
|
||||
HostType.VISA_MASTER -> "Visa/Master"
|
||||
}
|
||||
|
||||
internal fun searchReprintAnyTransactions(
|
||||
transactions: List<PayDetail>,
|
||||
query: String
|
||||
): List<PayDetail> {
|
||||
if (query.isBlank()) return transactions
|
||||
return when (query.length) {
|
||||
6 -> transactions.filter { it.voucherNo == query }
|
||||
12 -> transactions.filter { it.referNo == query }
|
||||
else -> transactions.filter {
|
||||
it.voucherNo.contains(query) || it.referNo.contains(query)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseTransDate(value: String, formatter: SimpleDateFormat): Date? {
|
||||
return try {
|
||||
formatter.parse(value)
|
||||
} catch (_: ParseException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.ChevronRight
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||
import com.mob.utsmyanmar.ui.functions.FunctionButton
|
||||
import com.mob.utsmyanmar.ui.theme.Color
|
||||
|
||||
@Composable
|
||||
fun HistoryMenuScreen(
|
||||
onBack: () -> Unit,
|
||||
onReprintLastTransaction: () -> Unit,
|
||||
onReprintAnyTransaction: () -> Unit,
|
||||
onReprintLastSettlement: () -> Unit,
|
||||
onPrintDetailReport: () -> Unit,
|
||||
onPrintSummaryReport: () -> Unit,
|
||||
onReview: () -> Unit,
|
||||
onBatchTotal: () -> Unit,
|
||||
) {
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Select Function",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
HistoryMenuButton("Reprint Last Transaction", onReprintLastTransaction)
|
||||
HistoryMenuButton("Reprint Any Transaction", onReprintAnyTransaction)
|
||||
HistoryMenuButton("Reprint Last Settlement Report", onReprintLastSettlement)
|
||||
HistoryMenuButton("Print Detail Report", onPrintDetailReport)
|
||||
HistoryMenuButton("Print Summary Report", onPrintSummaryReport)
|
||||
HistoryMenuButton("Review", onReview)
|
||||
HistoryMenuButton("Batch Total", onBatchTotal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HistoryMenuButton(
|
||||
title: String,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
FunctionButton(
|
||||
onClick = onClick,
|
||||
title = title,
|
||||
subTitle = "",
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = null,
|
||||
tint = Color.LegacyRed
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import com.utsmyanmar.paylibs.model.PayDetail
|
||||
import com.utsmyanmar.paylibs.print.PrintHelper
|
||||
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt
|
||||
import com.utsmyanmar.paylibs.print.printx.PrintXStatus
|
||||
|
||||
internal fun printSettlementReport(
|
||||
context: Context,
|
||||
payDetail: PayDetail,
|
||||
onSuccess: () -> Unit,
|
||||
onFailure: () -> Unit,
|
||||
) {
|
||||
if (PrintHelper.getInstance().paperRollStatus() != 1) {
|
||||
Toast.makeText(context, "Paper roll not ready.", Toast.LENGTH_SHORT).show()
|
||||
onFailure()
|
||||
return
|
||||
}
|
||||
|
||||
PrintXReceipt.getInstance().printSmileSettlementReport(
|
||||
payDetail,
|
||||
object : PrintXStatus {
|
||||
override fun onSuccess() {
|
||||
onSuccess()
|
||||
}
|
||||
|
||||
override fun onFailure() {
|
||||
onFailure()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,180 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||
import com.utsmyanmar.paylibs.model.PayDetail
|
||||
import com.utsmyanmar.paylibs.utils.PrintStatus
|
||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||
import com.utsmyanmar.paylibs.utils.enums.HostType
|
||||
import com.utsmyanmar.paylibs.utils.enums.TransMenu
|
||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||
|
||||
private sealed interface HistoryDestination {
|
||||
data object Menu : HistoryDestination
|
||||
data class SelectHost(val purpose: HistoryHostPurpose) : HistoryDestination
|
||||
data class ReprintAny(val hostType: HostType) : HistoryDestination
|
||||
data class DetailReport(val hostType: HostType) : HistoryDestination
|
||||
data class SummaryReport(val hostType: HostType) : HistoryDestination
|
||||
data object ReviewTrace : HistoryDestination
|
||||
data class ReviewDetail(val trace: String) : HistoryDestination
|
||||
data object BatchTotal : HistoryDestination
|
||||
data object ReprintSettlement : HistoryDestination
|
||||
data object NotFound : HistoryDestination
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HistoryRoute(
|
||||
sharedViewModel: SharedViewModel,
|
||||
onBack: () -> Unit,
|
||||
onNavigatePrintReceipt: () -> Unit,
|
||||
viewModel: HistoryViewModel = hiltViewModel(),
|
||||
) {
|
||||
var destination by remember { mutableStateOf<HistoryDestination>(HistoryDestination.Menu) }
|
||||
var hostPurpose by remember { mutableStateOf(HistoryHostPurpose.REPRINT_ANY) }
|
||||
|
||||
val voucherNo = SystemParamsOperation.getInstance().lastSuccessTrnx
|
||||
val lastTransactions by viewModel.getLastTransaction(voucherNo).observeAsState(emptyList())
|
||||
|
||||
fun navigateToHostSelection(purpose: HistoryHostPurpose) {
|
||||
hostPurpose = purpose
|
||||
destination = HistoryDestination.SelectHost(purpose)
|
||||
}
|
||||
|
||||
fun handleHostSelected(hostType: HostType) {
|
||||
sharedViewModel.hostType.value = hostType
|
||||
destination = when (hostPurpose) {
|
||||
HistoryHostPurpose.REPRINT_ANY ->
|
||||
HistoryDestination.ReprintAny(hostType)
|
||||
|
||||
HistoryHostPurpose.LAST_SETTLEMENT -> {
|
||||
if (hostType == HostType.MPU) {
|
||||
HistoryDestination.ReprintSettlement
|
||||
} else {
|
||||
HistoryDestination.NotFound
|
||||
}
|
||||
}
|
||||
|
||||
HistoryHostPurpose.DETAIL_REPORT ->
|
||||
HistoryDestination.DetailReport(hostType)
|
||||
|
||||
HistoryHostPurpose.SUMMARY_REPORT ->
|
||||
HistoryDestination.SummaryReport(hostType)
|
||||
}
|
||||
}
|
||||
|
||||
fun reprintTransaction(payDetail: PayDetail) {
|
||||
sharedViewModel.setTransMenu(TransMenu.REPRINT)
|
||||
sharedViewModel.isReprint.value = true
|
||||
sharedViewModel.payDetail.value = payDetail
|
||||
sharedViewModel.setPrintStatus(PrintStatus.FIRST_PRINT)
|
||||
onNavigatePrintReceipt()
|
||||
}
|
||||
|
||||
fun reprintLastTransaction() {
|
||||
sharedViewModel.setTransMenu(TransMenu.REPRINT)
|
||||
if (lastTransactions.isEmpty()) {
|
||||
destination = HistoryDestination.NotFound
|
||||
return
|
||||
}
|
||||
|
||||
val payDetail = lastTransactions.last()
|
||||
if (!isValidForReprint(payDetail)) {
|
||||
destination = HistoryDestination.NotFound
|
||||
return
|
||||
}
|
||||
|
||||
reprintTransaction(prepareReprintPayDetail(payDetail))
|
||||
}
|
||||
|
||||
when (val current = destination) {
|
||||
HistoryDestination.Menu -> HistoryMenuScreen(
|
||||
onBack = onBack,
|
||||
onReprintLastTransaction = ::reprintLastTransaction,
|
||||
onReprintAnyTransaction = {
|
||||
sharedViewModel.setTransMenu(TransMenu.TRANSACTIONS)
|
||||
sharedViewModel.transactionsType.value = null
|
||||
navigateToHostSelection(HistoryHostPurpose.REPRINT_ANY)
|
||||
},
|
||||
onReprintLastSettlement = {
|
||||
sharedViewModel.setTransMenu(TransMenu.LAST_SETTLEMENT)
|
||||
navigateToHostSelection(HistoryHostPurpose.LAST_SETTLEMENT)
|
||||
},
|
||||
onPrintDetailReport = {
|
||||
sharedViewModel.setTransMenu(TransMenu.DETAIL_REPORT)
|
||||
navigateToHostSelection(HistoryHostPurpose.DETAIL_REPORT)
|
||||
},
|
||||
onPrintSummaryReport = {
|
||||
sharedViewModel.setTransMenu(TransMenu.SUMMARY_REPORT)
|
||||
navigateToHostSelection(HistoryHostPurpose.SUMMARY_REPORT)
|
||||
},
|
||||
onReview = {
|
||||
sharedViewModel.setTransMenu(TransMenu.REVIEW)
|
||||
sharedViewModel.transactionsType.value = TransactionsType.REVIEW_TRANS
|
||||
destination = HistoryDestination.ReviewTrace
|
||||
},
|
||||
onBatchTotal = {
|
||||
sharedViewModel.setTransMenu(TransMenu.REVIEW_BATCH)
|
||||
destination = HistoryDestination.BatchTotal
|
||||
}
|
||||
)
|
||||
|
||||
is HistoryDestination.SelectHost -> SelectHostScreen(
|
||||
onBack = { destination = HistoryDestination.Menu },
|
||||
onSelectHost = ::handleHostSelected
|
||||
)
|
||||
|
||||
is HistoryDestination.ReprintAny -> ReprintAnyTransactionScreen(
|
||||
viewModel = viewModel,
|
||||
hostType = current.hostType,
|
||||
onBack = { destination = HistoryDestination.Menu },
|
||||
onReprintTransaction = ::reprintTransaction
|
||||
)
|
||||
|
||||
is HistoryDestination.DetailReport -> DetailReportScreen(
|
||||
viewModel = viewModel,
|
||||
hostType = current.hostType,
|
||||
onBack = { destination = HistoryDestination.Menu }
|
||||
)
|
||||
|
||||
is HistoryDestination.SummaryReport -> SummaryReportScreen(
|
||||
viewModel = viewModel,
|
||||
hostType = current.hostType,
|
||||
onBack = { destination = HistoryDestination.Menu }
|
||||
)
|
||||
|
||||
HistoryDestination.ReviewTrace -> ReviewTraceScreen(
|
||||
viewModel = viewModel,
|
||||
onBack = { destination = HistoryDestination.Menu },
|
||||
onNavigateReviewDetail = { trace ->
|
||||
destination = HistoryDestination.ReviewDetail(trace)
|
||||
}
|
||||
)
|
||||
|
||||
is HistoryDestination.ReviewDetail -> ReviewDetailScreen(
|
||||
viewModel = viewModel,
|
||||
trace = current.trace,
|
||||
onBack = { destination = HistoryDestination.ReviewTrace }
|
||||
)
|
||||
|
||||
HistoryDestination.BatchTotal -> BatchTotalScreen(
|
||||
viewModel = viewModel,
|
||||
onBack = { destination = HistoryDestination.Menu }
|
||||
)
|
||||
|
||||
HistoryDestination.ReprintSettlement -> ReprintSettlementScreen(
|
||||
viewModel = viewModel,
|
||||
onBack = { destination = HistoryDestination.Menu },
|
||||
onDone = onBack
|
||||
)
|
||||
|
||||
HistoryDestination.NotFound -> TransactionNotFoundScreen(
|
||||
onBack = { destination = HistoryDestination.Menu }
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import com.utsmyanmar.paylibs.model.PayDetail
|
||||
import com.utsmyanmar.paylibs.model.SettleData
|
||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||
import com.utsmyanmar.paylibs.utils.enums.HostType
|
||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
internal fun formatTime(hour: String, minute: String): String {
|
||||
if (hour.isBlank() || minute.isBlank()) return "Select"
|
||||
return "$hour:$minute"
|
||||
}
|
||||
|
||||
internal class SummaryCounter {
|
||||
var count = 0
|
||||
var amount = 0L
|
||||
|
||||
fun inc(value: Long) {
|
||||
count++
|
||||
amount += value
|
||||
}
|
||||
}
|
||||
|
||||
internal fun buildSummarySettleData(
|
||||
transactions: List<PayDetail>,
|
||||
hostType: HostType,
|
||||
start: Date,
|
||||
end: Date,
|
||||
): SettleData {
|
||||
val dateFormat = SimpleDateFormat("dd/MM/yy", Locale.getDefault())
|
||||
val dateTimeFormat = SimpleDateFormat("dd/MM/yy HH:mm", Locale.getDefault())
|
||||
val yesterday = POSUtil.getInstance().yesterdayDate
|
||||
|
||||
val wave = SummaryCounter()
|
||||
val waveRefund = SummaryCounter()
|
||||
val voidTran = SummaryCounter()
|
||||
val sale = SummaryCounter()
|
||||
val ca = SummaryCounter()
|
||||
val preAuth = SummaryCounter()
|
||||
val preAuthVoid = SummaryCounter()
|
||||
val preAuthComp = SummaryCounter()
|
||||
val preAuthCompVoid = SummaryCounter()
|
||||
val refund = SummaryCounter()
|
||||
|
||||
for (pay in transactions) {
|
||||
val transDate = try {
|
||||
dateFormat.parse(pay.transDate)
|
||||
} catch (_: ParseException) {
|
||||
continue
|
||||
} ?: continue
|
||||
|
||||
if (yesterday.after(transDate)) continue
|
||||
|
||||
val currentDate = try {
|
||||
dateTimeFormat.parse("${pay.transDate} ${pay.transTime}")
|
||||
} catch (_: ParseException) {
|
||||
continue
|
||||
} ?: continue
|
||||
|
||||
if (currentDate.before(start) || currentDate.after(end)) continue
|
||||
|
||||
when (hostType) {
|
||||
HostType.QR -> when (pay.transactionType) {
|
||||
TransactionsType.WAVEPAY.value ->
|
||||
if (pay.qrTransStatus == 1) wave.inc(pay.amount)
|
||||
|
||||
TransactionsType.WAVEPAY_REFUND.value ->
|
||||
if (pay.qrTransStatus == 1) waveRefund.inc(pay.amount)
|
||||
}
|
||||
|
||||
HostType.MPU -> if (pay.accountType == "MPU") {
|
||||
accumulateCardSummary(
|
||||
pay, sale, voidTran, ca, preAuth, preAuthVoid, preAuthComp, preAuthCompVoid, refund
|
||||
)
|
||||
}
|
||||
|
||||
HostType.VISA_MASTER -> if (pay.accountType != "MPU") {
|
||||
accumulateCardSummary(
|
||||
pay, sale, voidTran, ca, preAuth, preAuthVoid, preAuthComp, preAuthCompVoid, refund
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SettleData(
|
||||
sale.count, sale.amount,
|
||||
wave.count, wave.amount,
|
||||
voidTran.count, voidTran.amount,
|
||||
ca.count, ca.amount,
|
||||
preAuth.count, preAuth.amount,
|
||||
preAuthVoid.count, preAuthVoid.amount,
|
||||
preAuthComp.count, preAuthComp.amount,
|
||||
preAuthCompVoid.count, preAuthCompVoid.amount,
|
||||
refund.count, refund.amount,
|
||||
waveRefund.count, waveRefund.amount
|
||||
)
|
||||
}
|
||||
|
||||
private fun accumulateCardSummary(
|
||||
pay: PayDetail,
|
||||
sale: SummaryCounter,
|
||||
voidTran: SummaryCounter,
|
||||
ca: SummaryCounter,
|
||||
preAuth: SummaryCounter,
|
||||
preAuthVoid: SummaryCounter,
|
||||
preAuthComp: SummaryCounter,
|
||||
preAuthCompVoid: SummaryCounter,
|
||||
refund: SummaryCounter,
|
||||
) {
|
||||
when (pay.transactionType) {
|
||||
TransactionsType.VOID.value -> voidTran.inc(pay.amount)
|
||||
TransactionsType.SALE.value -> sale.inc(pay.amount)
|
||||
TransactionsType.CASH_OUT.value -> ca.inc(pay.amount)
|
||||
TransactionsType.PRE_AUTH_SALE.value -> preAuth.inc(pay.amount)
|
||||
TransactionsType.PRE_AUTH_VOID.value -> preAuthVoid.inc(pay.amount)
|
||||
TransactionsType.PRE_AUTH_COMPLETE.value -> preAuthComp.inc(pay.amount)
|
||||
TransactionsType.PRE_AUTH_COMPLETE_VOID.value -> preAuthCompVoid.inc(pay.amount)
|
||||
TransactionsType.REFUND.value -> refund.inc(pay.amount)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.utsmyanmar.baselib.repo.Repository
|
||||
import com.utsmyanmar.paylibs.model.PayDetail
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class HistoryViewModel @Inject constructor(
|
||||
private val repository: Repository
|
||||
) : ViewModel() {
|
||||
|
||||
fun getTransactionHistory(): LiveData<List<PayDetail>> =
|
||||
repository.getTransactionHistory()
|
||||
|
||||
fun getLastTransaction(voucherNo: String): LiveData<List<PayDetail>> =
|
||||
repository.getLastTransaction(voucherNo)
|
||||
|
||||
fun getLastSettlement(voucherNo: String): LiveData<List<PayDetail>> =
|
||||
repository.getLastSettlement(voucherNo)
|
||||
|
||||
fun getReviewBatchTransaction(batchNo: String): LiveData<List<PayDetail>> =
|
||||
repository.getReviewBatchTransaction(batchNo)
|
||||
|
||||
fun getSmileSummaryTrans(batchNo: String): LiveData<List<PayDetail>> =
|
||||
repository.getSmileSummaryTrans(batchNo)
|
||||
|
||||
fun searchTransaction(voucherNo: String): LiveData<PayDetail> =
|
||||
repository.searchTransaction(voucherNo)
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
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.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.enums.HostType
|
||||
|
||||
@Composable
|
||||
fun ReprintAnyTransactionScreen(
|
||||
viewModel: HistoryViewModel,
|
||||
hostType: HostType,
|
||||
onBack: () -> Unit,
|
||||
onReprintTransaction: (PayDetail) -> Unit,
|
||||
) {
|
||||
val allTransactions by viewModel.getTransactionHistory().observeAsState(emptyList())
|
||||
var searchQuery by remember { mutableStateOf("") }
|
||||
|
||||
val filtered = remember(allTransactions, hostType, searchQuery) {
|
||||
val base = filterReprintAnyTransactions(allTransactions, hostType)
|
||||
searchReprintAnyTransactions(base, searchQuery.trim())
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Transactions",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = searchQuery,
|
||||
onValueChange = { searchQuery = it },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
label = { Text("Trace (6) or RRN (12)") },
|
||||
singleLine = true
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
if (filtered.isEmpty()) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text("No transactions found.", color = Color.Gray)
|
||||
}
|
||||
} else {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
items(filtered, key = { "${it.voucherNo}_${it.referNo}_${it.PID}" }) { payDetail ->
|
||||
HistoryTransactionCard(payDetail) {
|
||||
onReprintTransaction(prepareReprintPayDetail(payDetail))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.core_utils.SystemParamsOperation
|
||||
|
||||
@Composable
|
||||
fun ReprintSettlementScreen(
|
||||
viewModel: HistoryViewModel,
|
||||
onBack: () -> Unit,
|
||||
onDone: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val voucherNo = SystemParamsOperation.getInstance().currentSerialNum
|
||||
val settlements by viewModel.getLastSettlement(voucherNo).observeAsState(emptyList())
|
||||
var payDetail by remember { mutableStateOf<PayDetail?>(null) }
|
||||
var hasStarted by remember { mutableStateOf(false) }
|
||||
var printFailed by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(settlements) {
|
||||
if (hasStarted) return@LaunchedEffect
|
||||
if (settlements.isEmpty()) {
|
||||
Toast.makeText(context, "No transactions to print.", Toast.LENGTH_SHORT).show()
|
||||
onBack()
|
||||
return@LaunchedEffect
|
||||
}
|
||||
hasStarted = true
|
||||
val detail = prepareReprintPayDetail(settlements.last())
|
||||
payDetail = detail
|
||||
printSettlementReport(context, detail, onSuccess = onDone) {
|
||||
printFailed = true
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(title = "Printing Settlement Report")
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
if (printFailed) {
|
||||
Text("Printing settlement report failed.", color = Color.LegacyRed)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Button(
|
||||
onClick = {
|
||||
payDetail?.let { detail ->
|
||||
printSettlementReport(context, detail, onSuccess = onDone) {
|
||||
printFailed = true
|
||||
}
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.LegacyRed,
|
||||
contentColor = Color.White
|
||||
)
|
||||
) {
|
||||
Text("Retry")
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
TextButton(onClick = onDone) {
|
||||
Text("Done")
|
||||
}
|
||||
} else {
|
||||
CircularProgressIndicator(color = Color.LegacyRed)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text("Printing settlement report...")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
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.unit.dp
|
||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||
import com.mob.utsmyanmar.ui.theme.Color
|
||||
|
||||
@Composable
|
||||
fun ReviewDetailScreen(
|
||||
viewModel: HistoryViewModel,
|
||||
trace: String,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
val transaction by viewModel.searchTransaction(trace).observeAsState()
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Transaction Info",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
transaction?.let { payDetail ->
|
||||
HistoryTransactionDetailCard(payDetail)
|
||||
} ?: Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text("Transaction not found.", color = Color.Gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,142 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
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.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.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||
import com.mob.utsmyanmar.ui.theme.Color
|
||||
import com.utsmyanmar.paylibs.model.PayDetail
|
||||
|
||||
@Composable
|
||||
fun ReviewTraceScreen(
|
||||
viewModel: HistoryViewModel,
|
||||
onBack: () -> Unit,
|
||||
onNavigateReviewDetail: (String) -> Unit,
|
||||
) {
|
||||
var traceNumber by remember { mutableStateOf("") }
|
||||
var searchedTrace by remember { mutableStateOf("") }
|
||||
var lastNavigatedTrace by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
val transactionSource: LiveData<PayDetail?> = remember(searchedTrace) {
|
||||
if (searchedTrace.isBlank()) {
|
||||
MutableLiveData(null)
|
||||
} else {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
viewModel.searchTransaction(searchedTrace) as LiveData<PayDetail?>
|
||||
}
|
||||
}
|
||||
val transaction by transactionSource.observeAsState()
|
||||
|
||||
LaunchedEffect(transaction?.voucherNo) {
|
||||
val matchedTrace = transaction?.voucherNo ?: return@LaunchedEffect
|
||||
if (lastNavigatedTrace == matchedTrace) return@LaunchedEffect
|
||||
lastNavigatedTrace = matchedTrace
|
||||
onNavigateReviewDetail(matchedTrace)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Review",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = if (searchedTrace.isNotBlank() && transaction == null) {
|
||||
"No transaction found for trace $searchedTrace."
|
||||
} else {
|
||||
"Input trace number to review transaction."
|
||||
},
|
||||
color = if (searchedTrace.isNotBlank() && transaction == null) {
|
||||
Color.LegacyRed
|
||||
} else {
|
||||
Color.Black
|
||||
},
|
||||
fontSize = 14.sp
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||
) {
|
||||
Text(
|
||||
text = traceNumber.padStart(6, '0').ifEmpty { "000000" },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(24.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 28.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
HistoryNumericKeypad(
|
||||
onDigit = { digit ->
|
||||
if (traceNumber.length < 6) traceNumber += digit
|
||||
},
|
||||
onBackspace = {
|
||||
if (traceNumber.isNotEmpty()) {
|
||||
traceNumber = traceNumber.dropLast(1)
|
||||
}
|
||||
},
|
||||
onClear = { traceNumber = "" }
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Button(
|
||||
onClick = { searchedTrace = traceNumber.padStart(6, '0') },
|
||||
enabled = traceNumber.isNotBlank(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.LegacyRed,
|
||||
contentColor = Color.White
|
||||
)
|
||||
) {
|
||||
Text("Search")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
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.AlertDialog
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ElevatedButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
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.utils.core_utils.SystemParamsOperation
|
||||
import com.utsmyanmar.paylibs.utils.enums.HostType
|
||||
|
||||
@Composable
|
||||
fun SelectHostScreen(
|
||||
onBack: () -> Unit,
|
||||
onSelectHost: (HostType) -> Unit,
|
||||
) {
|
||||
var unavailableMessage by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Select Host",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
HostButton("MPU") { onSelectHost(HostType.MPU) }
|
||||
HostButton("Visa / Master") {
|
||||
if (SystemParamsOperation.getInstance().isEmvEnabled) {
|
||||
onSelectHost(HostType.VISA_MASTER)
|
||||
} else {
|
||||
unavailableMessage = "Currently this menu is unavailable!"
|
||||
}
|
||||
}
|
||||
HostButton("QR Pay") { onSelectHost(HostType.QR) }
|
||||
}
|
||||
}
|
||||
|
||||
unavailableMessage?.let { message ->
|
||||
AlertDialog(
|
||||
onDismissRequest = { unavailableMessage = null },
|
||||
confirmButton = {
|
||||
TextButton(onClick = { unavailableMessage = null }) {
|
||||
Text("OK")
|
||||
}
|
||||
},
|
||||
text = { Text(message) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HostButton(
|
||||
label: String,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
ElevatedButton(
|
||||
onClick = onClick,
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.White,
|
||||
contentColor = Color.Black
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(64.dp)
|
||||
) {
|
||||
Text(label, fontSize = 16.sp, fontWeight = FontWeight.SemiBold)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,220 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import android.app.DatePickerDialog
|
||||
import android.app.TimePickerDialog
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
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.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||
import com.mob.utsmyanmar.ui.theme.Color
|
||||
import com.utsmyanmar.paylibs.print.PrintHelper
|
||||
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt
|
||||
import com.utsmyanmar.paylibs.print.printx.PrintXStatus
|
||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||
import com.utsmyanmar.paylibs.utils.enums.HostType
|
||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||
import com.utsmyanmar.paylibs.utils.params.Params
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
@Composable
|
||||
fun SummaryReportScreen(
|
||||
viewModel: HistoryViewModel,
|
||||
hostType: HostType,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val calendarStart = remember { Calendar.getInstance() }
|
||||
val calendarEnd = remember { Calendar.getInstance() }
|
||||
|
||||
var startDate by remember { mutableStateOf("") }
|
||||
var endDate by remember { mutableStateOf("") }
|
||||
var startHour by remember { mutableStateOf("") }
|
||||
var startMinute by remember { mutableStateOf("") }
|
||||
var endHour by remember { mutableStateOf("") }
|
||||
var endMinute by remember { mutableStateOf("") }
|
||||
var isPrinting by remember { mutableStateOf(false) }
|
||||
var errorMessage by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
val allTransactions by viewModel.getSmileSummaryTrans(
|
||||
SystemParamsOperation.getInstance().currentBatchNum
|
||||
).observeAsState(emptyList())
|
||||
|
||||
fun showDatePicker(isStart: Boolean) {
|
||||
val calendar = if (isStart) calendarStart else calendarEnd
|
||||
DatePickerDialog(
|
||||
context,
|
||||
{ _, year, month, day ->
|
||||
calendar.set(year, month, day)
|
||||
val formatted = SimpleDateFormat("dd/MM/yy", Locale.getDefault())
|
||||
.format(calendar.time)
|
||||
if (isStart) startDate = formatted else endDate = formatted
|
||||
},
|
||||
calendar.get(Calendar.YEAR),
|
||||
calendar.get(Calendar.MONTH),
|
||||
calendar.get(Calendar.DAY_OF_MONTH)
|
||||
).show()
|
||||
}
|
||||
|
||||
fun showTimePicker(isStart: Boolean) {
|
||||
val calendar = if (isStart) calendarStart else calendarEnd
|
||||
TimePickerDialog(
|
||||
context,
|
||||
{ _, hour, minute ->
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour)
|
||||
calendar.set(Calendar.MINUTE, minute)
|
||||
val hr = String.format(Locale.getDefault(), "%02d", hour)
|
||||
val min = String.format(Locale.getDefault(), "%02d", minute)
|
||||
if (isStart) {
|
||||
startHour = hr
|
||||
startMinute = min
|
||||
} else {
|
||||
endHour = hr
|
||||
endMinute = min
|
||||
}
|
||||
},
|
||||
calendar.get(Calendar.HOUR_OF_DAY),
|
||||
calendar.get(Calendar.MINUTE),
|
||||
false
|
||||
).show()
|
||||
}
|
||||
|
||||
fun printSummaryReport() {
|
||||
if (startDate.isBlank() || endDate.isBlank() ||
|
||||
startHour.isBlank() || startMinute.isBlank() ||
|
||||
endHour.isBlank() || endMinute.isBlank()
|
||||
) {
|
||||
errorMessage = "Please select date and time!"
|
||||
return
|
||||
}
|
||||
|
||||
val pattern = "dd/MM/yy HH:mm"
|
||||
val formatter = SimpleDateFormat(pattern, Locale.getDefault())
|
||||
val start: Date
|
||||
val end: Date
|
||||
try {
|
||||
start = formatter.parse("$startDate $startHour:$startMinute") ?: return
|
||||
end = formatter.parse("$endDate $endHour:$endMinute") ?: return
|
||||
} catch (_: ParseException) {
|
||||
errorMessage = "Invalid date or time."
|
||||
return
|
||||
}
|
||||
|
||||
if (start.after(end)) {
|
||||
errorMessage = "Invalid end date!"
|
||||
return
|
||||
}
|
||||
|
||||
val settleData = buildSummarySettleData(allTransactions, hostType, start, end)
|
||||
if (settleData.saleCount + settleData.wavePayCount +
|
||||
settleData.voidSaleCount + settleData.cashAdvanceCount +
|
||||
settleData.preAuthCount + settleData.refundCount + settleData.waveRefundCount == 0
|
||||
) {
|
||||
errorMessage = "No transactions to print."
|
||||
return
|
||||
}
|
||||
|
||||
if (PrintHelper.getInstance().paperRollStatus() != 1) {
|
||||
errorMessage = "Paper roll not ready."
|
||||
return
|
||||
}
|
||||
|
||||
val tradeData = Params.newTrade(false)
|
||||
val payDetail = tradeData.payDetail
|
||||
payDetail.settleDataObj = settleData
|
||||
payDetail.transType = TransactionsType.SUMMARY_REPORT.name
|
||||
payDetail.transactionType = TransactionsType.SUMMARY_REPORT.value
|
||||
payDetail.accountType = hostTypeAccountLabel(hostType)
|
||||
|
||||
isPrinting = true
|
||||
PrintXReceipt.getInstance().printSmileSummaryReport(
|
||||
payDetail,
|
||||
object : PrintXStatus {
|
||||
override fun onSuccess() {
|
||||
isPrinting = false
|
||||
}
|
||||
|
||||
override fun onFailure() {
|
||||
isPrinting = false
|
||||
errorMessage = "Print failed."
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Transaction Summary",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
SummaryPickerRow("Start Date", startDate.ifBlank { "Select" }) { showDatePicker(true) }
|
||||
SummaryPickerRow("Start Time", formatTime(startHour, startMinute)) { showTimePicker(true) }
|
||||
SummaryPickerRow("End Date", endDate.ifBlank { "Select" }) { showDatePicker(false) }
|
||||
SummaryPickerRow("End Time", formatTime(endHour, endMinute)) { showTimePicker(false) }
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Button(
|
||||
onClick = ::printSummaryReport,
|
||||
enabled = !isPrinting,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.LegacyRed,
|
||||
contentColor = Color.White
|
||||
)
|
||||
) {
|
||||
Text(if (isPrinting) "Printing..." else "Print")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errorMessage?.let { message ->
|
||||
AlertDialog(
|
||||
onDismissRequest = { errorMessage = null },
|
||||
confirmButton = {
|
||||
TextButton(onClick = { errorMessage = null }) {
|
||||
Text("OK")
|
||||
}
|
||||
},
|
||||
text = { Text(message) }
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.mob.utsmyanmar.ui.history_functions
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||
import com.mob.utsmyanmar.ui.theme.Color
|
||||
|
||||
@Composable
|
||||
fun TransactionNotFoundScreen(onBack: () -> Unit) {
|
||||
Scaffold(
|
||||
containerColor = Color.IvoryBeige,
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = "Transaction Info",
|
||||
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
onIconClick = onBack
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = "Transaction not found.",
|
||||
color = Color.Gray,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,7 @@ import com.mob.utsmyanmar.ui.dashboard.DashboardViewModel
|
||||
import com.mob.utsmyanmar.ui.device_info.DeviceInfoViewModel
|
||||
import com.mob.utsmyanmar.ui.disable.DisableScreen
|
||||
import com.mob.utsmyanmar.ui.functions.FunctionsScreen
|
||||
import com.mob.utsmyanmar.ui.history_functions.HistoryRoute
|
||||
import com.mob.utsmyanmar.ui.input_amount.AmountRoute
|
||||
import com.mob.utsmyanmar.ui.manual_entry.InputManualCardRoute
|
||||
import com.mob.utsmyanmar.ui.notification.NotificationDetailScreen
|
||||
@ -158,6 +159,11 @@ fun AppNavGraph(
|
||||
launchSingleTop = true
|
||||
}
|
||||
},
|
||||
onNavigateHistory = {
|
||||
navController.navigate(Routes.Password.createRoute(Routes.History.route, PasswordType.SYSTEM)) {
|
||||
launchSingleTop = true
|
||||
}
|
||||
},
|
||||
onNavigateAction = { action ->
|
||||
when (action) {
|
||||
"Void" -> {
|
||||
@ -225,6 +231,24 @@ fun AppNavGraph(
|
||||
)
|
||||
}
|
||||
|
||||
composable(Routes.History.route) {
|
||||
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
||||
val transResultViewModel: TransactionResultViewModel = hiltViewModel(activity)
|
||||
HistoryRoute(
|
||||
sharedViewModel = sharedViewModel,
|
||||
onBack = { navController.popBackStack() },
|
||||
onNavigatePrintReceipt = {
|
||||
transResultViewModel.onEvent(
|
||||
TransactionResultEvent.Start,
|
||||
sharedViewModel
|
||||
)
|
||||
navController.navigate(Routes.PrintReceipt.route) {
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composable(Routes.VoidTrace.route) {
|
||||
val voidViewModel: VoidViewModel = hiltViewModel()
|
||||
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
||||
|
||||
@ -40,6 +40,7 @@ sealed class Routes(val route: String) {
|
||||
data object NotificationDetail : Routes("notification_detail/{notificationId}") {
|
||||
fun createRoute(id: Int): String = "notification_detail/$id"
|
||||
}
|
||||
data object History : Routes("history")
|
||||
data object Disable : Routes("disable/{message}") {
|
||||
fun createRoute(message: String): String = "disable/${Uri.encode(message)}"
|
||||
}
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
package com.mob.utsmyanmar.ui.sending_to_host
|
||||
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
@ -12,19 +8,12 @@ import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||
import com.mob.utsmyanmar.viewmodel.TransProcessViewModel
|
||||
import kotlinx.coroutines.delay
|
||||
import androidx.compose.runtime.getValue
|
||||
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultState
|
||||
import com.mob.utsmyanmar.viewmodel.ProcessingTransaction
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.mob.utsmyanmar.model.TransactionStatus
|
||||
import com.mob.utsmyanmar.ui.settlement.SettlementViewModel
|
||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
|
||||
private const val MOCK_HOST_DELAY_MS = 2000L
|
||||
|
||||
@ -43,8 +32,6 @@ fun ProcessingRoute(
|
||||
|
||||
val settlementStatus by settlementViewModel.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
var showReversalDialog by rememberSaveable { mutableStateOf(false) }
|
||||
var reversalMessage by rememberSaveable { mutableStateOf("") }
|
||||
|
||||
if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) {
|
||||
LaunchedEffect(Unit) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user