Compare commits
8 Commits
ee91e6f787
...
4884152faa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4884152faa | ||
|
|
beb6ddcba8 | ||
|
|
b2e8e13a81 | ||
|
|
511c3e0128 | ||
|
|
40c392cc01 | ||
|
|
86f3e099db | ||
|
|
f4d9dfaf7b | ||
|
|
b3cb166f1a |
@ -40,8 +40,8 @@ android {
|
|||||||
dimension = "env"
|
dimension = "env"
|
||||||
applicationIdSuffix = ".uat"
|
applicationIdSuffix = ".uat"
|
||||||
versionNameSuffix = "-UAT"
|
versionNameSuffix = "-UAT"
|
||||||
versionCode = 12
|
versionCode = 14
|
||||||
versionName = "3.0"
|
versionName = "3.2"
|
||||||
buildConfigField("String", "ENV", "\"UAT\"")
|
buildConfigField("String", "ENV", "\"UAT\"")
|
||||||
resValue("string", "app_name", "MOB-UAT")
|
resValue("string", "app_name", "MOB-UAT")
|
||||||
}
|
}
|
||||||
|
|||||||
10
app/changelog.md
Normal file
10
app/changelog.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
## Change Logs For UAT
|
||||||
|
|
||||||
|
### version 3.3
|
||||||
|
* config auto update after transaction
|
||||||
|
* signature removed on void
|
||||||
|
* "Enter Password" color to LegacyRed
|
||||||
|
* Amount and Card Number show in signature pad
|
||||||
|
* fixed recent transaction only working for top 3
|
||||||
|
* routed to dashboard after printing receipt
|
||||||
|
* receipt printing animation re-scale
|
||||||
@ -25,24 +25,25 @@ class DashboardMenuItem(
|
|||||||
val onClick: () -> Unit
|
val onClick: () -> Unit
|
||||||
)
|
)
|
||||||
|
|
||||||
val settlementEnabled = false
|
|
||||||
val voidEnabled = true
|
|
||||||
val refundEnabled = true
|
|
||||||
val preAuthEnabled = true
|
|
||||||
val preAuthVoidEnabled = true
|
|
||||||
val preAuthCompleteEnabled = true
|
|
||||||
val preAuthCompleteVoidEnabled = true
|
|
||||||
val cashAdvEnabled = true
|
|
||||||
|
|
||||||
fun buildMenuItems(
|
fun buildMenuItems(
|
||||||
onNavigateAmount: (String) -> Unit,
|
onNavigateAmount: (String) -> Unit,
|
||||||
onNavigateSignOn: () -> Unit,
|
onNavigateSignOn: () -> Unit,
|
||||||
onNavigateSettlement: () -> Unit,
|
onNavigateSettlement: () -> Unit,
|
||||||
onNavigateHistory: () -> Unit,
|
onNavigateHistory: () -> Unit,
|
||||||
onNavigateAction: (String) -> Unit
|
onNavigateAction: (String) -> Unit
|
||||||
): List<DashboardMenuItem> = buildList {
|
): List<DashboardMenuItem> {
|
||||||
|
val sp = SystemParamsOperation.getInstance()
|
||||||
|
val settlementEnabled = sp.settlementStatus
|
||||||
|
val voidEnabled = sp.voidStatus
|
||||||
|
val refundEnabled = sp.refundStatus
|
||||||
|
val preAuthEnabled = sp.preAuthStatus
|
||||||
|
val preAuthVoidEnabled = sp.preAuthStatus
|
||||||
|
val preAuthCompleteEnabled = sp.preAuthStatus
|
||||||
|
val preAuthCompleteVoidEnabled = sp.preAuthStatus
|
||||||
|
val cashAdvEnabled = sp.cashAdvanceStatus
|
||||||
|
val mmqrEnabled = sp.mmqrStatus
|
||||||
|
return buildList {
|
||||||
|
|
||||||
val mmqrEnabled = SystemParamsOperation.getInstance().mmqrStatus
|
|
||||||
|
|
||||||
add(
|
add(
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
@ -59,175 +60,174 @@ fun buildMenuItems(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if (mmqrEnabled) {
|
if (mmqrEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"MMQR",
|
||||||
|
{
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.drawable.ic_mmqr_logo),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.height(48.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { }
|
||||||
|
)
|
||||||
|
}
|
||||||
add(
|
add(
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"MMQR",
|
"History",
|
||||||
{
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.ic_mmqr_logo),
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.height(48.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"History",
|
|
||||||
{
|
|
||||||
Icon(
|
|
||||||
painterResource(R.drawable.ic_history),
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(32.dp),
|
|
||||||
tint = Color.LegacyRed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { onNavigateHistory() }
|
|
||||||
)
|
|
||||||
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"Sign On",
|
|
||||||
{
|
|
||||||
Icon(
|
|
||||||
painterResource(R.drawable.ic_sign_on),
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(32.dp),
|
|
||||||
tint = Color.LegacyRed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { onNavigateSignOn() }
|
|
||||||
)
|
|
||||||
|
|
||||||
if (settlementEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"Settlement",
|
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
painterResource(R.drawable.ic_settlement),
|
painterResource(R.drawable.ic_history),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { onNavigateSettlement() }
|
) { onNavigateHistory() }
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if (voidEnabled) {
|
|
||||||
add(
|
add(
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Void",
|
"Sign On",
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Default.Lock,
|
painterResource(R.drawable.ic_sign_on),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { onNavigateAction("Void") }
|
) { onNavigateSignOn() }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (settlementEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"Settlement",
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
painterResource(R.drawable.ic_settlement),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { onNavigateSettlement() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (voidEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"Void",
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Lock,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { onNavigateAction("Void") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refundEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"Refund",
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Replay,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { onNavigateAction("Refund") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preAuthEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"Pre-Auth",
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Lock,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { onNavigateAmount("Pre-Auth") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preAuthVoidEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"Pre-Auth Void",
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Default.LockOpen,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { onNavigateAction("Pre-Auth Void") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preAuthCompleteEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"Pre-Auth Complete",
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Default.CreditCard,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { onNavigateAction("Pre-Auth Complete") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preAuthCompleteVoidEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"Pre-Auth Comp Void",
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Default.SwapHoriz,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { onNavigateAction("Pre-Auth Complete Void") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cashAdvEnabled) {
|
||||||
|
add(
|
||||||
|
DashboardMenuItem(
|
||||||
|
"Cash Adv",
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Default.AccountBalanceWallet,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { onNavigateAmount("Cash Adv") }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refundEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"Refund",
|
|
||||||
{
|
|
||||||
Icon(
|
|
||||||
Icons.Default.Replay,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(32.dp),
|
|
||||||
tint = Color.LegacyRed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { onNavigateAction("Refund") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preAuthEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"Pre-Auth",
|
|
||||||
{
|
|
||||||
Icon(
|
|
||||||
Icons.Default.Lock,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(32.dp),
|
|
||||||
tint = Color.LegacyRed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { onNavigateAmount("Pre-Auth") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preAuthVoidEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"Pre-Auth Void",
|
|
||||||
{
|
|
||||||
Icon(
|
|
||||||
Icons.Default.LockOpen,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(32.dp),
|
|
||||||
tint = Color.LegacyRed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { onNavigateAction("Pre-Auth Void") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preAuthCompleteEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"Pre-Auth Complete",
|
|
||||||
{
|
|
||||||
Icon(
|
|
||||||
Icons.Default.CreditCard,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(32.dp),
|
|
||||||
tint = Color.LegacyRed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { onNavigateAction("Pre-Auth Complete") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preAuthCompleteVoidEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"Pre-Auth Comp Void",
|
|
||||||
{
|
|
||||||
Icon(
|
|
||||||
Icons.Default.SwapHoriz,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(32.dp),
|
|
||||||
tint = Color.LegacyRed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { onNavigateAction("Pre-Auth Complete Void") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cashAdvEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"Cash Adv",
|
|
||||||
{
|
|
||||||
Icon(
|
|
||||||
Icons.Default.AccountBalanceWallet,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.size(32.dp),
|
|
||||||
tint = Color.LegacyRed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { onNavigateAmount("Cash Adv") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -92,6 +92,8 @@ fun AppNavGraph(
|
|||||||
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
||||||
SignaturePad(
|
SignaturePad(
|
||||||
onBack = { navController.popBackStack() },
|
onBack = { navController.popBackStack() },
|
||||||
|
amount = sharedViewModel.payDetail.value?.amount,
|
||||||
|
cardNumber = sharedViewModel.payDetail.value?.cardNo ?: "",
|
||||||
onConfirm = { bitmap, signatureBlob ->
|
onConfirm = { bitmap, signatureBlob ->
|
||||||
sharedViewModel.signBitmap = bitmap
|
sharedViewModel.signBitmap = bitmap
|
||||||
sharedViewModel.updateSignatureBlob(signatureBlob)
|
sharedViewModel.updateSignatureBlob(signatureBlob)
|
||||||
@ -111,10 +113,10 @@ fun AppNavGraph(
|
|||||||
val transResultViewModel: TransactionResultViewModel = hiltViewModel(activity)
|
val transResultViewModel: TransactionResultViewModel = hiltViewModel(activity)
|
||||||
val dashboardViewModel: DashboardViewModel = hiltViewModel(activity)
|
val dashboardViewModel: DashboardViewModel = hiltViewModel(activity)
|
||||||
val dashboardUiState = dashboardViewModel.uiState.collectAsStateWithLifecycle().value
|
val dashboardUiState = dashboardViewModel.uiState.collectAsStateWithLifecycle().value
|
||||||
val recentPayDetails by sharedViewModel.getLastThreeTransactions().observeAsState(emptyList())
|
val recentPayDetails by sharedViewModel.getLastTenTransactions().observeAsState(emptyList())
|
||||||
val deviceInfoViewModel: DeviceInfoViewModel = hiltViewModel(activity)
|
val deviceInfoViewModel: DeviceInfoViewModel = hiltViewModel(activity)
|
||||||
val deviceInfoUiState = deviceInfoViewModel.uiState.collectAsStateWithLifecycle().value
|
val deviceInfoUiState = deviceInfoViewModel.uiState.collectAsStateWithLifecycle().value
|
||||||
val tmsSetupViewModel: TmsSetupViewModel = hiltViewModel();
|
val tmsSetupViewModel: TmsSetupViewModel = hiltViewModel(activity);
|
||||||
|
|
||||||
LaunchedEffect(deviceInfoViewModel) {
|
LaunchedEffect(deviceInfoViewModel) {
|
||||||
deviceInfoViewModel.loadDeviceInfo()
|
deviceInfoViewModel.loadDeviceInfo()
|
||||||
@ -750,9 +752,14 @@ fun AppNavGraph(
|
|||||||
composable(Routes.TransactionResult.route) {
|
composable(Routes.TransactionResult.route) {
|
||||||
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
||||||
val transResultViewModel: TransactionResultViewModel = hiltViewModel(activity)
|
val transResultViewModel: TransactionResultViewModel = hiltViewModel(activity)
|
||||||
|
val tmsSetupViewModel: TmsSetupViewModel = hiltViewModel(activity)
|
||||||
|
val dashboardViewModel: DashboardViewModel = hiltViewModel(activity)
|
||||||
|
|
||||||
TransactionResultRoute(
|
TransactionResultRoute(
|
||||||
viewModel = transResultViewModel,
|
viewModel = transResultViewModel,
|
||||||
sharedViewModel = sharedViewModel,
|
sharedViewModel = sharedViewModel,
|
||||||
|
tmsSetupViewModel = tmsSetupViewModel,
|
||||||
|
dashboardViewModel = dashboardViewModel,
|
||||||
onNavigateMain = {
|
onNavigateMain = {
|
||||||
navController.navigate(Routes.Dashboard.route) {
|
navController.navigate(Routes.Dashboard.route) {
|
||||||
popUpTo(Routes.Dashboard.route) {
|
popUpTo(Routes.Dashboard.route) {
|
||||||
@ -794,6 +801,14 @@ fun AppNavGraph(
|
|||||||
}
|
}
|
||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onPrintFinished = {
|
||||||
|
navController.navigate(Routes.Dashboard.route) {
|
||||||
|
popUpTo(Routes.Dashboard.route) {
|
||||||
|
inclusive = false
|
||||||
|
}
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,7 +112,7 @@ fun InputPassword(
|
|||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(text = "Enter Password", color = Color.Gray, fontSize = 18.sp)
|
Text(text = "Enter Password", color = Color.LegacyRed, fontSize = 18.sp)
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
PasswordDots(filledCount = uiState.input.length, totalCount = PASSWORD_LENGTH)
|
PasswordDots(filledCount = uiState.input.length, totalCount = PASSWORD_LENGTH)
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
|
|||||||
@ -44,9 +44,7 @@ import com.mob.utsmyanmar.ui.transaction_result.TransactionResultViewModel
|
|||||||
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||||
import com.utsmyanmar.paylibs.utils.PrintStatus
|
import com.utsmyanmar.paylibs.utils.PrintStatus
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
|
||||||
|
|
||||||
private enum class ReceiptCopy(val label: String) {
|
private enum class ReceiptCopy(val label: String) {
|
||||||
MERCHANT("MERCHANT COPY"),
|
MERCHANT("MERCHANT COPY"),
|
||||||
@ -58,12 +56,12 @@ fun PrintReceiptScreen(
|
|||||||
transactionResultViewModel: TransactionResultViewModel,
|
transactionResultViewModel: TransactionResultViewModel,
|
||||||
sharedViewModel: SharedViewModel,
|
sharedViewModel: SharedViewModel,
|
||||||
onPrint: () -> Unit,
|
onPrint: () -> Unit,
|
||||||
onDone: () -> Unit
|
onDone: () -> Unit,
|
||||||
|
onPrintFinished : () -> Unit,
|
||||||
) {
|
) {
|
||||||
val state by transactionResultViewModel.state.collectAsStateWithLifecycle()
|
val state by transactionResultViewModel.state.collectAsStateWithLifecycle()
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val receiptOffsetY = remember { Animatable(0f) }
|
val receiptOffsetY = remember { Animatable(0f) }
|
||||||
val animationDuration = 5000
|
|
||||||
val merchant_copy_autoprint = true
|
val merchant_copy_autoprint = true
|
||||||
val customer_copy_autoprint = false
|
val customer_copy_autoprint = false
|
||||||
var currentCopy by remember { mutableStateOf(ReceiptCopy.MERCHANT) }
|
var currentCopy by remember { mutableStateOf(ReceiptCopy.MERCHANT) }
|
||||||
@ -72,10 +70,10 @@ fun PrintReceiptScreen(
|
|||||||
|
|
||||||
suspend fun animatePrint() {
|
suspend fun animatePrint() {
|
||||||
receiptOffsetY.animateTo(
|
receiptOffsetY.animateTo(
|
||||||
targetValue = -1500f,
|
targetValue = -1400f,
|
||||||
animationSpec = tween(durationMillis = animationDuration, easing = FastOutSlowInEasing)
|
animationSpec = tween(durationMillis = 4000, easing = FastOutSlowInEasing)
|
||||||
)
|
)
|
||||||
delay(1000.milliseconds)
|
// delay(1000.milliseconds)
|
||||||
receiptOffsetY.animateTo(
|
receiptOffsetY.animateTo(
|
||||||
targetValue = 0f,
|
targetValue = 0f,
|
||||||
animationSpec = tween(durationMillis = 0, easing = FastOutSlowInEasing)
|
animationSpec = tween(durationMillis = 0, easing = FastOutSlowInEasing)
|
||||||
@ -84,21 +82,30 @@ fun PrintReceiptScreen(
|
|||||||
|
|
||||||
fun isReprintMode() = sharedViewModel.isReprint.value == true
|
fun isReprintMode() = sharedViewModel.isReprint.value == true
|
||||||
|
|
||||||
fun doPrint(copy: ReceiptCopy, onFinished: () -> Unit) {
|
fun doPrint(copy: ReceiptCopy, onFinished: (printFinished: ReceiptCopy) -> Unit) {
|
||||||
val reprint = isReprintMode()
|
val reprint = isReprintMode()
|
||||||
val actualCopy = if (reprint && copy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else copy
|
val actualCopy = if (reprint && copy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else copy
|
||||||
currentCopy = actualCopy
|
currentCopy = actualCopy
|
||||||
|
|
||||||
sharedViewModel.setPrintStatus(
|
sharedViewModel.setPrintStatus(
|
||||||
if (actualCopy == ReceiptCopy.MERCHANT) PrintStatus.FIRST_PRINT else PrintStatus.SECOND_PRINT
|
if (actualCopy == ReceiptCopy.MERCHANT)
|
||||||
|
PrintStatus.FIRST_PRINT
|
||||||
|
else
|
||||||
|
PrintStatus.SECOND_PRINT
|
||||||
)
|
)
|
||||||
onPrint()
|
onPrint()
|
||||||
scope.launch {
|
scope.launch {
|
||||||
isPrinting = true
|
isPrinting = true
|
||||||
animatePrint()
|
animatePrint()
|
||||||
isPrinting = false
|
isPrinting = false
|
||||||
nextCopy = if (reprint) ReceiptCopy.CUSTOMER
|
val upcomingCopy = if (reprint) ReceiptCopy.CUSTOMER
|
||||||
else if (actualCopy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else ReceiptCopy.MERCHANT
|
else if (actualCopy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER
|
||||||
onFinished()
|
else ReceiptCopy.CUSTOMER
|
||||||
|
|
||||||
|
currentCopy = upcomingCopy
|
||||||
|
nextCopy = upcomingCopy
|
||||||
|
|
||||||
|
onFinished(actualCopy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +181,12 @@ fun PrintReceiptScreen(
|
|||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
doPrint(nextCopy) { }
|
doPrint(nextCopy) { printFinished ->
|
||||||
|
if (printFinished == ReceiptCopy.CUSTOMER) {
|
||||||
|
onPrintFinished()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
@ -295,7 +307,8 @@ fun PreviewPrintReceiptScreen() {
|
|||||||
sharedViewModel = hiltViewModel(),
|
sharedViewModel = hiltViewModel(),
|
||||||
transactionResultViewModel = hiltViewModel(),
|
transactionResultViewModel = hiltViewModel(),
|
||||||
onPrint = {},
|
onPrint = {},
|
||||||
onDone = {}
|
onDone = {},
|
||||||
|
onPrintFinished = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ fun ProcessingRoute(
|
|||||||
when(transStatus) {
|
when(transStatus) {
|
||||||
TransResultStatus.SUCCESS -> {
|
TransResultStatus.SUCCESS -> {
|
||||||
sharedViewModel.payDetail.value = transProcessViewModel.payDetailResult.value
|
sharedViewModel.payDetail.value = transProcessViewModel.payDetailResult.value
|
||||||
if (requiresSignature(sharedViewModel.payDetail.value)) {
|
if (requiresSignature(sharedViewModel.transactionsType.value, sharedViewModel.payDetail.value)) {
|
||||||
onNavigateSignature()
|
onNavigateSignature()
|
||||||
} else {
|
} else {
|
||||||
onNavigateTransactionResult()
|
onNavigateTransactionResult()
|
||||||
@ -94,7 +94,9 @@ fun ProcessingRoute(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requiresSignature(payDetail: com.utsmyanmar.paylibs.model.PayDetail?): Boolean {
|
private fun requiresSignature(transType: TransactionsType?, payDetail: com.utsmyanmar.paylibs.model.PayDetail?): Boolean {
|
||||||
// return payDetail?.transCVM == TransCVM.SIGNATURE && payDetail.isFreeSign == false
|
if (transType == TransactionsType.VOID || transType == TransactionsType.PRE_AUTH_COMPLETE_VOID || transType == TransactionsType.PRE_AUTH_VOID) {
|
||||||
return true;
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.mob.utsmyanmar.ui.signature_pad
|
package com.mob.utsmyanmar.ui.signature_pad
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@ -15,16 +16,21 @@ 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.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
|
||||||
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
|
||||||
|
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.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
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.theme.MOBPOSTheme
|
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
|
||||||
|
import com.mob.utsmyanmar.utils.formatAmount
|
||||||
|
import com.mob.utsmyanmar.utils.maskCardNumber
|
||||||
import se.warting.signaturepad.SignaturePadAdapter
|
import se.warting.signaturepad.SignaturePadAdapter
|
||||||
import se.warting.signaturepad.SignaturePadView
|
import se.warting.signaturepad.SignaturePadView
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
@ -34,9 +40,13 @@ import com.mob.utsmyanmar.ui.theme.Color as AppColor
|
|||||||
fun SignaturePad(
|
fun SignaturePad(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onBack: () -> Unit = {},
|
onBack: () -> Unit = {},
|
||||||
onConfirm: (Bitmap?, ByteArray?) -> Unit = { _, _ -> }
|
onConfirm: (Bitmap?, ByteArray?) -> Unit = { _, _ -> },
|
||||||
|
amount: Long? = 0L,
|
||||||
|
cardNumber: String,
|
||||||
) {
|
) {
|
||||||
var signaturePadAdapter: SignaturePadAdapter? = null
|
var signaturePadAdapter: SignaturePadAdapter? = null
|
||||||
|
var selectedMode by remember { mutableStateOf(SignatureMode.Digital) }
|
||||||
|
val isManualMode = selectedMode == SignatureMode.Manual
|
||||||
|
|
||||||
val scaledWidth = 300
|
val scaledWidth = 300
|
||||||
|
|
||||||
@ -69,33 +79,137 @@ fun SignaturePad(
|
|||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
) {
|
) {
|
||||||
SignaturePadView(
|
|
||||||
onReady = { signaturePadAdapter = it },
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier.padding(0.dp),
|
||||||
.fillMaxWidth()
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
.height(200.dp)
|
) {
|
||||||
.border(width = 1.dp, color = AppColor.LegacyRed)
|
Text(
|
||||||
)
|
text = "Amount",
|
||||||
|
style = MaterialTheme.typography.titleSmall,
|
||||||
|
color = AppColor.LegacyRed
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = amount.formatAmount(),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = AppColor.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(0.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Card Number",
|
||||||
|
style = MaterialTheme.typography.titleSmall,
|
||||||
|
color = AppColor.LegacyRed
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = cardNumber.maskCardNumber(),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = AppColor.LegacyRed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isManualMode) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(200.dp),
|
||||||
|
shape = RoundedCornerShape(8.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.White),
|
||||||
|
border = androidx.compose.foundation.BorderStroke(
|
||||||
|
width = 1.dp,
|
||||||
|
color = AppColor.Gray.copy(alpha = 0.35f)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = androidx.compose.ui.Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Manual Signature",
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
color = AppColor.Gray
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Customer need to sign on paper",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = AppColor.Gray.copy(alpha = 0.7f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SignaturePadView(
|
||||||
|
onReady = { signaturePadAdapter = it },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(200.dp)
|
||||||
|
.background(AppColor.White)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = AppColor.LegacyRed,
|
||||||
|
shape = RoundedCornerShape(8.dp)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
SignatureModeOption(
|
||||||
|
title = "Digital",
|
||||||
|
subtitle = "Sign on screen",
|
||||||
|
selected = !isManualMode,
|
||||||
|
onClick = { selectedMode = SignatureMode.Digital },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
SignatureModeOption(
|
||||||
|
title = "Manual",
|
||||||
|
subtitle = "Sign on paper",
|
||||||
|
selected = isManualMode,
|
||||||
|
onClick = { selectedMode = SignatureMode.Manual },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
OutlinedButton(
|
Button(
|
||||||
onClick = { signaturePadAdapter?.clear() },
|
onClick = {
|
||||||
|
if (!isManualMode) {
|
||||||
|
signaturePadAdapter?.clear()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = AppColor.White,
|
||||||
|
contentColor = Color.White
|
||||||
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.height(50.dp)
|
.height(50.dp),
|
||||||
|
enabled = !isManualMode
|
||||||
) {
|
) {
|
||||||
Text("Clear")
|
Text("Clear", color = AppColor.Black)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
val rawBitmap = signaturePadAdapter?.getSignatureBitmap()
|
if (isManualMode) {
|
||||||
val bitmap = rawBitmap?.let { scaleBitmap(it) }
|
onConfirm(null, null)
|
||||||
val signatureBlob = bitmap?.let { bitmapToBlob(it) }
|
} else {
|
||||||
onConfirm(bitmap, signatureBlob)
|
val rawBitmap = signaturePadAdapter?.getSignatureBitmap()
|
||||||
|
val bitmap = rawBitmap?.let { scaleBitmap(it) }
|
||||||
|
val signatureBlob = bitmap?.let { bitmapToBlob(it) }
|
||||||
|
onConfirm(bitmap, signatureBlob)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
@ -159,6 +273,9 @@ private fun SignatureModeOption(
|
|||||||
@Composable
|
@Composable
|
||||||
fun SignaturePadPreview() {
|
fun SignaturePadPreview() {
|
||||||
MOBPOSTheme {
|
MOBPOSTheme {
|
||||||
SignaturePad()
|
SignaturePad(
|
||||||
|
amount = 1000000L,
|
||||||
|
cardNumber = "6244310034582136"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
package com.mob.utsmyanmar.ui.transaction_result
|
||||||
|
|
||||||
|
class TransactionResultRepository {
|
||||||
|
}
|
||||||
@ -4,8 +4,9 @@ package com.mob.utsmyanmar.ui.transaction_result
|
|||||||
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.hilt.navigation.compose.hiltViewModel
|
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.mob.utsmyanmar.ui.dashboard.DashboardViewModel
|
||||||
|
import com.mob.utsmyanmar.ui.tms_setup.TmsSetupViewModel
|
||||||
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||||
|
|
||||||
@ -17,7 +18,9 @@ fun TransactionResultRoute(
|
|||||||
onNavigatePrintReceipt: () -> Unit,
|
onNavigatePrintReceipt: () -> Unit,
|
||||||
onShowError: (String) -> Unit,
|
onShowError: (String) -> Unit,
|
||||||
onShowSuccess: (String) -> Unit,
|
onShowSuccess: (String) -> Unit,
|
||||||
onShowPrinterDialog: (String) -> Unit
|
onShowPrinterDialog: (String) -> Unit,
|
||||||
|
tmsSetupViewModel: TmsSetupViewModel,
|
||||||
|
dashboardViewModel: DashboardViewModel,
|
||||||
) {
|
) {
|
||||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||||
val canGoBack = sharedViewModel.transactionsType.value != TransactionsType.SALE
|
val canGoBack = sharedViewModel.transactionsType.value != TransactionsType.SALE
|
||||||
@ -27,6 +30,8 @@ fun TransactionResultRoute(
|
|||||||
TransactionResultEvent.Start,
|
TransactionResultEvent.Start,
|
||||||
sharedViewModel
|
sharedViewModel
|
||||||
)
|
)
|
||||||
|
dashboardViewModel.refreshLastSyncTime()
|
||||||
|
tmsSetupViewModel.downloadConfigs()
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
|||||||
20
app/src/main/java/com/mob/utsmyanmar/utils/Converter.kt
Normal file
20
app/src/main/java/com/mob/utsmyanmar/utils/Converter.kt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.mob.utsmyanmar.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
fun Long?.formatAmount(): String {
|
||||||
|
val amount = (this ?: 0L) / 100.0
|
||||||
|
return String.format("%,.2f", amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String?.maskCardNumber(): String {
|
||||||
|
if (this.isNullOrEmpty()) return ""
|
||||||
|
val maskedPan = StringBuilder(this)
|
||||||
|
if (this.length > 12) {
|
||||||
|
maskedPan.replace(6, 12, "******")
|
||||||
|
} else {
|
||||||
|
maskedPan.append(" ")
|
||||||
|
}
|
||||||
|
return maskedPan.toString()
|
||||||
|
}
|
||||||
@ -438,6 +438,10 @@ class SharedViewModel @Inject constructor(
|
|||||||
return repository.getLastThreeTransactions()
|
return repository.getLastThreeTransactions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getLastTenTransactions(): LiveData<List<PayDetail>> {
|
||||||
|
return repository.getLastTenTransactions()
|
||||||
|
}
|
||||||
|
|
||||||
fun getSettlementRecords(): LiveData<List<PayDetail>> {
|
fun getSettlementRecords(): LiveData<List<PayDetail>> {
|
||||||
return repository.getSettlementPOS()
|
return repository.getSettlementPOS()
|
||||||
}
|
}
|
||||||
|
|||||||
11
opencode.json
Normal file
11
opencode.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://opencode.ai/config.json",
|
||||||
|
"mcp": {
|
||||||
|
"codebase-memory": {
|
||||||
|
"type": "local",
|
||||||
|
"command": "codebase-memory-mcp",
|
||||||
|
"args": [],
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user