Compare commits
No commits in common. "fc4b8173089480a25a81b7568bd02c78e6399c2b" and "7c0e9c4e66bda46d915e00d1fbbcc7b20f216404" have entirely different histories.
fc4b817308
...
7c0e9c4e66
@ -5,6 +5,9 @@ plugins {
|
|||||||
id("com.google.dagger.hilt.android")
|
id("com.google.dagger.hilt.android")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set default build variant
|
||||||
|
project.ext.set("android.defaultPublishConfig", "uatDebug")
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.mob.utsmyanmar"
|
namespace = "com.mob.utsmyanmar"
|
||||||
compileSdk {
|
compileSdk {
|
||||||
@ -40,8 +43,8 @@ android {
|
|||||||
dimension = "env"
|
dimension = "env"
|
||||||
applicationIdSuffix = ".uat"
|
applicationIdSuffix = ".uat"
|
||||||
versionNameSuffix = "-UAT"
|
versionNameSuffix = "-UAT"
|
||||||
versionCode = 12
|
versionCode = 3
|
||||||
versionName = "3.0"
|
versionName = "2.1"
|
||||||
buildConfigField("String", "ENV", "\"UAT\"")
|
buildConfigField("String", "ENV", "\"UAT\"")
|
||||||
resValue("string", "app_name", "MOB-UAT")
|
resValue("string", "app_name", "MOB-UAT")
|
||||||
}
|
}
|
||||||
@ -59,14 +62,6 @@ android {
|
|||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
debug {
|
|
||||||
isMinifyEnabled = false
|
|
||||||
isDebuggable = true
|
|
||||||
// proguardFiles(
|
|
||||||
// getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
||||||
// "proguard-rules.pro"
|
|
||||||
// )
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
@ -125,6 +120,4 @@ dependencies {
|
|||||||
implementation(project(":ecr"))
|
implementation(project(":ecr"))
|
||||||
implementation(project(":xpay"))
|
implementation(project(":xpay"))
|
||||||
implementation(project(":cmhl"))
|
implementation(project(":cmhl"))
|
||||||
|
|
||||||
implementation("se.warting.signature:signature-pad:0.2.0")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,8 +29,6 @@
|
|||||||
<application
|
<application
|
||||||
android:name="com.mob.utsmyanmar.MyApplication"
|
android:name="com.mob.utsmyanmar.MyApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
|
||||||
android:usesCleartextTraffic="true"
|
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package com.mob.utsmyanmar.ui.cardwaiting
|
|||||||
|
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@ -39,9 +38,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@ -137,16 +134,16 @@ private fun CardWaitingScreenContent(
|
|||||||
Text(
|
Text(
|
||||||
text = "AMOUNT TO PAY",
|
text = "AMOUNT TO PAY",
|
||||||
color = Color.Black,
|
color = Color.Black,
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = MaterialTheme.typography.labelSmall
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(6.dp))
|
Spacer(modifier = Modifier.height(6.dp))
|
||||||
|
|
||||||
// Row(verticalAlignment = Alignment.Bottom) {
|
Row(verticalAlignment = Alignment.Bottom) {
|
||||||
Text(
|
Text(
|
||||||
text = amount,
|
text = amount,
|
||||||
color = Color.LegacyRed,
|
color = Color.LegacyRed,
|
||||||
style = MaterialTheme.typography.displayLarge
|
style = MaterialTheme.typography.displayMedium
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(6.dp))
|
Spacer(modifier = Modifier.width(6.dp))
|
||||||
@ -154,16 +151,16 @@ private fun CardWaitingScreenContent(
|
|||||||
Text(
|
Text(
|
||||||
text = "MMK",
|
text = "MMK",
|
||||||
color = Color.LegacyRed,
|
color = Color.LegacyRed,
|
||||||
style = MaterialTheme.typography.displaySmall.copy(fontWeight = FontWeight.Medium),
|
style = MaterialTheme.typography.labelSmall,
|
||||||
modifier = Modifier.padding(bottom = 6.dp)
|
modifier = Modifier.padding(bottom = 6.dp)
|
||||||
)
|
)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Spacer(modifier = Modifier.height(32.dp))
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
|
|
||||||
ContactlessCircle(isLoading = uiState.isLoading)
|
ContactlessCircle(isLoading = uiState.isLoading)
|
||||||
|
|
||||||
// Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = when {
|
text = when {
|
||||||
@ -209,9 +206,12 @@ private fun CardWaitingScreenContent(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
InsertCardRow(onMockClick = onMockClick)
|
InsertCardRow(onMockClick = onMockClick)
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
|
||||||
|
Spacer(modifier = Modifier.height(18.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = uiState.alertMessage,
|
text = uiState.alertMessage,
|
||||||
color = Color.Black,
|
color = Color.Black,
|
||||||
@ -219,13 +219,23 @@ private fun CardWaitingScreenContent(
|
|||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
lineHeight = 16.sp
|
lineHeight = 16.sp
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
|
||||||
|
Spacer(modifier = Modifier.height(18.dp))
|
||||||
|
|
||||||
|
// StatusPanel(uiState = uiState)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
ManualEntryAction(onManualEntryClick = onManualEntryClick)
|
ManualEntryAction(onManualEntryClick = onManualEntryClick)
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
|
||||||
|
Spacer(modifier = Modifier.height(18.dp))
|
||||||
|
|
||||||
CardLogoRow()
|
CardLogoRow()
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(34.dp))
|
Spacer(modifier = Modifier.height(34.dp))
|
||||||
|
|
||||||
PoweredByMob()
|
PoweredByMob()
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -291,8 +301,7 @@ private fun InsertCardRow(onMockClick: () -> Unit) {
|
|||||||
painter = painterResource(id = R.drawable.ic_insert_card),
|
painter = painterResource(id = R.drawable.ic_insert_card),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = Color.LegacyRed,
|
tint = Color.LegacyRed,
|
||||||
modifier = Modifier
|
modifier = Modifier.size(28.dp)
|
||||||
.size(28.dp)
|
|
||||||
.clickable(onClick = onMockClick)
|
.clickable(onClick = onMockClick)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -386,49 +395,13 @@ private fun CardLogoRow() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(42.dp)
|
.height(42.dp)
|
||||||
.padding(horizontal = 14.dp),
|
.padding(horizontal = 14.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
CardLogo(
|
Text("VISA", style = MaterialTheme.typography.titleLarge)
|
||||||
icon = painterResource(R.drawable.logo_visa),
|
Text("MC", style = MaterialTheme.typography.titleMedium)
|
||||||
name = "visa",
|
Text("MPU", style = MaterialTheme.typography.titleLarge)
|
||||||
)
|
Text("UnionPay", style = MaterialTheme.typography.labelMedium)
|
||||||
CardLogo(
|
|
||||||
icon = painterResource(R.drawable.logo_master),
|
|
||||||
name = "master",
|
|
||||||
)
|
|
||||||
CardLogo(
|
|
||||||
icon = painterResource(R.drawable.logo_mpu),
|
|
||||||
name = "master",
|
|
||||||
)
|
|
||||||
CardLogo(
|
|
||||||
icon = painterResource(R.drawable.logo_union_pay),
|
|
||||||
name = "master",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun CardLogo(
|
|
||||||
icon: Painter,
|
|
||||||
name: String,
|
|
||||||
modifier: Modifier = Modifier
|
|
||||||
) {
|
|
||||||
Surface(
|
|
||||||
modifier = modifier,
|
|
||||||
shape = RoundedCornerShape(4.dp),
|
|
||||||
color = Color.White
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
painter = icon,
|
|
||||||
contentDescription = name,
|
|
||||||
modifier = Modifier.height(30.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,13 +16,14 @@ import com.utsmyanmar.ecr.ECRHelper
|
|||||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.channels.Channel
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import sunmi.sunmiui.utils.LogUtil
|
||||||
|
|
||||||
class CardWaitingViewModel(
|
class CardWaitingViewModel(
|
||||||
private val cardReadViewModel: CardReaderViewModel,
|
private val cardReadViewModel: CardReaderViewModel,
|
||||||
|
|||||||
@ -5,14 +5,14 @@ import androidx.compose.material3.CenterAlignedTopAppBar
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.lifecycle.compose.dropUnlessResumed
|
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
|
import com.mob.utsmyanmar.ui.theme.Primary
|
||||||
import com.mob.utsmyanmar.ui.theme.White
|
import com.mob.utsmyanmar.ui.theme.White
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@ -35,7 +35,7 @@ fun AppBar(
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
if (icon != null && onIconClick != null) {
|
if (icon != null && onIconClick != null) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = dropUnlessResumed { onIconClick() }
|
onClick = onIconClick
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = icon,
|
imageVector = icon,
|
||||||
|
|||||||
@ -104,9 +104,7 @@ fun SummaryCard(
|
|||||||
onClickLastSync: () -> Unit,
|
onClickLastSync: () -> Unit,
|
||||||
lastSyncTime: Long?,
|
lastSyncTime: Long?,
|
||||||
totalSaleCount: Int,
|
totalSaleCount: Int,
|
||||||
totalSaleAmount: Long,
|
totalSaleAmount: Long
|
||||||
settlementStatusText: String,
|
|
||||||
settlementDateTimeText: String
|
|
||||||
) {
|
) {
|
||||||
var now by remember { mutableLongStateOf(System.currentTimeMillis()) }
|
var now by remember { mutableLongStateOf(System.currentTimeMillis()) }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
@ -147,8 +145,8 @@ fun SummaryCard(
|
|||||||
|
|
||||||
SummaryItem(
|
SummaryItem(
|
||||||
title = "Settlement",
|
title = "Settlement",
|
||||||
value = settlementStatusText,
|
value = "Completed",
|
||||||
subtitle = settlementDateTimeText,
|
subtitle = "Today 11:00 PM",
|
||||||
icon = Icons.Default.Check,
|
icon = Icons.Default.Check,
|
||||||
iconBg = Color.CrimsonRed
|
iconBg = Color.CrimsonRed
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
package com.mob.utsmyanmar.ui.dashboard
|
package com.mob.utsmyanmar.ui.dashboard
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.AccountBalanceWallet
|
import androidx.compose.material.icons.filled.AccountBalanceWallet
|
||||||
import androidx.compose.material.icons.filled.CreditCard
|
import androidx.compose.material.icons.filled.CreditCard
|
||||||
@ -10,6 +7,7 @@ import androidx.compose.material.icons.filled.Lock
|
|||||||
import androidx.compose.material.icons.filled.LockOpen
|
import androidx.compose.material.icons.filled.LockOpen
|
||||||
import androidx.compose.material.icons.filled.Replay
|
import androidx.compose.material.icons.filled.Replay
|
||||||
import androidx.compose.material.icons.filled.SwapHoriz
|
import androidx.compose.material.icons.filled.SwapHoriz
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@ -17,7 +15,6 @@ import androidx.compose.ui.res.painterResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.mob.utsmyanmar.R
|
import com.mob.utsmyanmar.R
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
|
||||||
|
|
||||||
class DashboardMenuItem(
|
class DashboardMenuItem(
|
||||||
val title: String,
|
val title: String,
|
||||||
@ -25,26 +22,13 @@ 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> = listOf(
|
||||||
|
|
||||||
val mmqrEnabled = SystemParamsOperation.getInstance().mmqrStatus
|
|
||||||
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Sale",
|
"Sale",
|
||||||
{
|
{
|
||||||
@ -54,26 +38,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(40.dp),
|
modifier = Modifier.size(40.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateAmount("Sale") },
|
||||||
) { onNavigateAmount("Sale") }
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if (mmqrEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
|
||||||
"MMQR",
|
|
||||||
{
|
|
||||||
Image(
|
|
||||||
painter = painterResource(R.drawable.ic_mmqr_logo),
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.height(48.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"History",
|
"History",
|
||||||
{
|
{
|
||||||
@ -83,11 +48,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateHistory() },
|
||||||
) { onNavigateHistory() }
|
|
||||||
)
|
|
||||||
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Sign On",
|
"Sign On",
|
||||||
{
|
{
|
||||||
@ -97,12 +58,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateSignOn() },
|
||||||
) { onNavigateSignOn() }
|
|
||||||
)
|
|
||||||
|
|
||||||
if (settlementEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Settlement",
|
"Settlement",
|
||||||
{
|
{
|
||||||
@ -112,13 +68,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateSettlement() },
|
||||||
) { onNavigateSettlement() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (voidEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Void",
|
"Void",
|
||||||
{
|
{
|
||||||
@ -128,13 +78,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateAction("Void") },
|
||||||
) { onNavigateAction("Void") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (refundEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Refund",
|
"Refund",
|
||||||
{
|
{
|
||||||
@ -144,13 +88,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateAction("Refund") },
|
||||||
) { onNavigateAction("Refund") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preAuthEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Pre-Auth",
|
"Pre-Auth",
|
||||||
{
|
{
|
||||||
@ -160,13 +98,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateAmount("Pre-Auth") },
|
||||||
) { onNavigateAmount("Pre-Auth") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preAuthVoidEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Pre-Auth Void",
|
"Pre-Auth Void",
|
||||||
{
|
{
|
||||||
@ -176,13 +108,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateAction("Pre-Auth Void") },
|
||||||
) { onNavigateAction("Pre-Auth Void") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preAuthCompleteEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Pre-Auth Complete",
|
"Pre-Auth Complete",
|
||||||
{
|
{
|
||||||
@ -192,13 +118,7 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateAction("Pre-Auth Complete") },
|
||||||
) { onNavigateAction("Pre-Auth Complete") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preAuthCompleteVoidEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Pre-Auth Comp Void",
|
"Pre-Auth Comp Void",
|
||||||
{
|
{
|
||||||
@ -208,15 +128,9 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateAction("Pre-Auth Complete Void") },
|
||||||
) { onNavigateAction("Pre-Auth Complete Void") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cashAdvEnabled) {
|
|
||||||
add(
|
|
||||||
DashboardMenuItem(
|
DashboardMenuItem(
|
||||||
"Cash Adv",
|
"Cash Out",
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Default.AccountBalanceWallet,
|
Icons.Default.AccountBalanceWallet,
|
||||||
@ -224,10 +138,5 @@ fun buildMenuItems(
|
|||||||
modifier = Modifier.size(32.dp),
|
modifier = Modifier.size(32.dp),
|
||||||
tint = Color.LegacyRed
|
tint = Color.LegacyRed
|
||||||
)
|
)
|
||||||
}
|
}) { onNavigateAmount("Cash Out") },
|
||||||
) { onNavigateAmount("Cash Adv") }
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@ -23,9 +23,6 @@ import androidx.compose.material.icons.filled.Menu
|
|||||||
import androidx.compose.material.icons.filled.Notifications
|
import androidx.compose.material.icons.filled.Notifications
|
||||||
import androidx.compose.material.icons.filled.Sync
|
import androidx.compose.material.icons.filled.Sync
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Card
|
|
||||||
import androidx.compose.material3.CardDefaults
|
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
|
||||||
import androidx.compose.material3.DrawerValue
|
import androidx.compose.material3.DrawerValue
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
@ -50,7 +47,6 @@ import androidx.compose.ui.layout.ContentScale
|
|||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
|
||||||
import com.mob.utsmyanmar.R
|
import com.mob.utsmyanmar.R
|
||||||
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||||
import com.mob.utsmyanmar.ui.device_info.DeviceInfoUiState
|
import com.mob.utsmyanmar.ui.device_info.DeviceInfoUiState
|
||||||
@ -180,29 +176,6 @@ fun DashboardScreen2(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dashboardUiState.isSyncing) {
|
|
||||||
Dialog(onDismissRequest = {}) {
|
|
||||||
Card(
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
colors = CardDefaults.cardColors(containerColor = Color.White),
|
|
||||||
elevation = CardDefaults.cardElevation(8.dp)
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(32.dp),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
CircularProgressIndicator(color = Color.LegacyRed)
|
|
||||||
Spacer(Modifier.height(16.dp))
|
|
||||||
Text(
|
|
||||||
text = dashboardUiState.syncStatusText,
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = Color.Black
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ModalNavigationDrawer(
|
ModalNavigationDrawer(
|
||||||
drawerState = drawerState,
|
drawerState = drawerState,
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
@ -421,9 +394,7 @@ fun DashboardScreen2(
|
|||||||
onClickLastSync = onClickLastSync,
|
onClickLastSync = onClickLastSync,
|
||||||
lastSyncTime = dashboardUiState.lastSyncTime,
|
lastSyncTime = dashboardUiState.lastSyncTime,
|
||||||
totalSaleCount = dashboardUiState.totalSaleCount,
|
totalSaleCount = dashboardUiState.totalSaleCount,
|
||||||
totalSaleAmount = dashboardUiState.totalSaleAmount,
|
totalSaleAmount = dashboardUiState.totalSaleAmount
|
||||||
settlementStatusText = dashboardUiState.settlementStatusText,
|
|
||||||
settlementDateTimeText = dashboardUiState.settlementDateTimeText
|
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(12.dp))
|
Spacer(Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,9 +15,5 @@ data class DashboardUiState(
|
|||||||
val lastSyncTime: Long? = null,
|
val lastSyncTime: Long? = null,
|
||||||
val carouselUrls: List<String> = emptyList(),
|
val carouselUrls: List<String> = emptyList(),
|
||||||
val totalSaleCount: Int = 0,
|
val totalSaleCount: Int = 0,
|
||||||
val totalSaleAmount: Long = 0L,
|
val totalSaleAmount: Long = 0L
|
||||||
val settlementStatusText: String = "Pending",
|
|
||||||
val settlementDateTimeText: String = "--/-- --:--",
|
|
||||||
val isSyncing: Boolean = false,
|
|
||||||
val syncStatusText: String = "Connecting to TMS server..."
|
|
||||||
)
|
)
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import androidx.lifecycle.asFlow
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.utsmyanmar.baselib.repo.Repository
|
import com.utsmyanmar.baselib.repo.Repository
|
||||||
import com.utsmyanmar.paylibs.model.PayDetail
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
import com.utsmyanmar.paylibs.system.SystemDateTime
|
|
||||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
@ -18,7 +17,6 @@ import kotlinx.coroutines.flow.update
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.util.Calendar
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
@ -33,23 +31,11 @@ class DashboardViewModel @Inject constructor(
|
|||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
repository.getLastTenTransactions().asFlow().collect { payDetails ->
|
repository.getLastTenTransactions().asFlow().collect { payDetails ->
|
||||||
val latestSettlement = payDetails.lastOrNull {
|
|
||||||
it.transactionType == TransactionsType.SETTLEMENT.value
|
|
||||||
}
|
|
||||||
val isCurrentBusinessSettlement = latestSettlement?.isCurrentBusinessSettlement() == true
|
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
recentTransactions = payDetails.map { pd -> pd.toRecord() },
|
recentTransactions = payDetails.map { pd -> pd.toRecord() },
|
||||||
totalSaleCount = payDetails.totalSaleCount(),
|
totalSaleCount = payDetails.totalSaleCount(),
|
||||||
totalSaleAmount = payDetails.totalSaleAmount(),
|
totalSaleAmount = payDetails.totalSaleAmount()
|
||||||
settlementStatusText = if (isCurrentBusinessSettlement) {
|
|
||||||
"Completed"
|
|
||||||
} else {
|
|
||||||
"Pending"
|
|
||||||
},
|
|
||||||
settlementDateTimeText = latestSettlement
|
|
||||||
?.let { buildDateTime(it.TradeDate, it.TradeTime) }
|
|
||||||
?: "--/-- --:--"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,18 +58,6 @@ class DashboardViewModel @Inject constructor(
|
|||||||
.takeIf { it > 0L }
|
.takeIf { it > 0L }
|
||||||
_uiState.update { it.copy(lastSyncTime = time) }
|
_uiState.update { it.copy(lastSyncTime = time) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startSync() {
|
|
||||||
_uiState.update { it.copy(isSyncing = true, syncStatusText = "Connecting to TMS server...") }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun finishSync(message: String) {
|
|
||||||
_uiState.update { it.copy(syncStatusText = message) }
|
|
||||||
viewModelScope.launch {
|
|
||||||
kotlinx.coroutines.delay(1500)
|
|
||||||
_uiState.update { it.copy(isSyncing = false) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PayDetail.toRecord(): TrnxRecord {
|
private fun PayDetail.toRecord(): TrnxRecord {
|
||||||
@ -127,7 +101,7 @@ private fun formatTypeLabel(raw: String): String = when {
|
|||||||
raw.contains("REFUND", ignoreCase = true) -> "Refund"
|
raw.contains("REFUND", ignoreCase = true) -> "Refund"
|
||||||
raw.contains("SETTLEMENT", ignoreCase = true) -> "Settlement"
|
raw.contains("SETTLEMENT", ignoreCase = true) -> "Settlement"
|
||||||
raw.contains("PRE", ignoreCase = true) -> "Pre-Auth"
|
raw.contains("PRE", ignoreCase = true) -> "Pre-Auth"
|
||||||
raw.contains("CASH", ignoreCase = true) -> "Cash Adv"
|
raw.contains("CASH", ignoreCase = true) -> "Cash Out"
|
||||||
raw.contains("WAVE", ignoreCase = true) -> "Wave Pay"
|
raw.contains("WAVE", ignoreCase = true) -> "Wave Pay"
|
||||||
else -> raw.lowercase().replaceFirstChar { it.uppercaseChar() }
|
else -> raw.lowercase().replaceFirstChar { it.uppercaseChar() }
|
||||||
}
|
}
|
||||||
@ -138,18 +112,3 @@ private fun buildDateTime(date: String?, time: String?): String {
|
|||||||
val t = (time ?: "").padStart(6, '0')
|
val t = (time ?: "").padStart(6, '0')
|
||||||
return "${d.take(2)}/${d.drop(2).take(2)} ${t.take(2)}:${t.drop(2).take(2)}"
|
return "${d.take(2)}/${d.drop(2).take(2)} ${t.take(2)}:${t.drop(2).take(2)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PayDetail.isCurrentBusinessSettlement(): Boolean {
|
|
||||||
if (transactionType != TransactionsType.SETTLEMENT.value) return false
|
|
||||||
if (TradeDate != SystemDateTime.getMMDD()) return false
|
|
||||||
|
|
||||||
val now = Calendar.getInstance()
|
|
||||||
val cutoff = Calendar.getInstance().apply {
|
|
||||||
set(Calendar.HOUR_OF_DAY, 23)
|
|
||||||
set(Calendar.MINUTE, 0)
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return now.before(cutoff)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ fun SeeMoreScreen(
|
|||||||
SeeMoreItem("Pre-Auth Void", Icons.Default.LockOpen),
|
SeeMoreItem("Pre-Auth Void", Icons.Default.LockOpen),
|
||||||
SeeMoreItem("Pre-Auth Complete", Icons.Default.CreditCard),
|
SeeMoreItem("Pre-Auth Complete", Icons.Default.CreditCard),
|
||||||
SeeMoreItem("Pre-Auth Complete Void", Icons.Default.SwapHoriz),
|
SeeMoreItem("Pre-Auth Complete Void", Icons.Default.SwapHoriz),
|
||||||
SeeMoreItem("Cash Adv", Icons.Default.AccountBalanceWallet)
|
SeeMoreItem("Cash Out", Icons.Default.AccountBalanceWallet)
|
||||||
)
|
)
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|||||||
@ -32,7 +32,7 @@ fun EmvTransactionRoute(
|
|||||||
onNavigateTransactionResult: () -> Unit,
|
onNavigateTransactionResult: () -> Unit,
|
||||||
onNavigateInputRrn: () -> Unit,
|
onNavigateInputRrn: () -> Unit,
|
||||||
onNavigateCardWaiting: () -> Unit,
|
onNavigateCardWaiting: () -> Unit,
|
||||||
onNavigateError: (isSuccess:Boolean, messsage:String) -> Unit,
|
onNavigateError: (String) -> Unit,
|
||||||
onNavigateMain: () -> Unit
|
onNavigateMain: () -> Unit
|
||||||
) {
|
) {
|
||||||
val emvResultStatus by emvViewModel.emvResultStatus.observeAsState()
|
val emvResultStatus by emvViewModel.emvResultStatus.observeAsState()
|
||||||
@ -69,7 +69,7 @@ fun EmvTransactionRoute(
|
|||||||
|
|
||||||
val tradeData = emvViewModel.getTradeData()
|
val tradeData = emvViewModel.getTradeData()
|
||||||
if (tradeData == null) {
|
if (tradeData == null) {
|
||||||
onNavigateError(false,"Please try again")
|
onNavigateError("Please try again")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,12 +115,12 @@ fun EmvTransactionRoute(
|
|||||||
|
|
||||||
EmvResultStatus.TRY_AGAIN -> {
|
EmvResultStatus.TRY_AGAIN -> {
|
||||||
sharedViewModel.set_errorFragmentMsg("Card Not Supported!")
|
sharedViewModel.set_errorFragmentMsg("Card Not Supported!")
|
||||||
onNavigateError(false,"Card Not Supported!")
|
onNavigateError("Card Not Supported!")
|
||||||
}
|
}
|
||||||
|
|
||||||
EmvResultStatus.OFFLINE_DECLINE -> {
|
EmvResultStatus.OFFLINE_DECLINE -> {
|
||||||
sharedViewModel.set_errorFragmentMsg("Offline Denial")
|
sharedViewModel.set_errorFragmentMsg("Offline Denial")
|
||||||
onNavigateError(false,"Offline Denial")
|
onNavigateError("Offline Denial")
|
||||||
}
|
}
|
||||||
|
|
||||||
EmvResultStatus.CONFIRM_CODE_VERIFY -> onNavigateCardWaiting()
|
EmvResultStatus.CONFIRM_CODE_VERIFY -> onNavigateCardWaiting()
|
||||||
@ -131,7 +131,7 @@ fun EmvTransactionRoute(
|
|||||||
|
|
||||||
EmvResultStatus.PIN_MISMATCH -> {
|
EmvResultStatus.PIN_MISMATCH -> {
|
||||||
sharedViewModel.set_errorFragmentMsg("PIN MISMATCH!")
|
sharedViewModel.set_errorFragmentMsg("PIN MISMATCH!")
|
||||||
onNavigateError(false,"PIN MISMATCH!")
|
onNavigateError("PIN MISMATCH!")
|
||||||
}
|
}
|
||||||
|
|
||||||
EmvResultStatus.PIN_EMPTY -> {
|
EmvResultStatus.PIN_EMPTY -> {
|
||||||
@ -164,27 +164,27 @@ fun EmvTransactionRoute(
|
|||||||
|
|
||||||
EmvResultStatus.REVERSAL_FAIL -> {
|
EmvResultStatus.REVERSAL_FAIL -> {
|
||||||
sharedViewModel.set_errorFragmentMsg("Reversal failed!")
|
sharedViewModel.set_errorFragmentMsg("Reversal failed!")
|
||||||
onNavigateError(false,"Reversal failed!")
|
onNavigateError("Reversal failed!")
|
||||||
}
|
}
|
||||||
|
|
||||||
EmvResultStatus.REVERSAL_SUCCESS -> {
|
EmvResultStatus.REVERSAL_SUCCESS -> {
|
||||||
sharedViewModel.set_successFragmentMsg("Reversal success!")
|
sharedViewModel.set_successFragmentMsg("Reversal success!")
|
||||||
onNavigateError(true,"Reversal success!")
|
onNavigateMain()
|
||||||
}
|
}
|
||||||
|
|
||||||
EmvResultStatus.FAIL -> {
|
EmvResultStatus.FAIL -> {
|
||||||
onNavigateError(false,"Transaction failed")
|
onNavigateError("Transaction failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
EmvResultStatus.NETWORK_ERROR -> {
|
EmvResultStatus.NETWORK_ERROR -> {
|
||||||
onNavigateError(false,"Com Error!")
|
onNavigateError("Com Error!")
|
||||||
}
|
}
|
||||||
|
|
||||||
EmvResultStatus.ERROR -> {
|
EmvResultStatus.ERROR -> {
|
||||||
loadingMessage = null
|
loadingMessage = null
|
||||||
val mapped = mapEmvError(errorCodeMsg)
|
val mapped = mapEmvError(errorCodeMsg)
|
||||||
sharedViewModel.set_errorFragmentMsg(mapped)
|
sharedViewModel.set_errorFragmentMsg(mapped)
|
||||||
onNavigateError(false,mapped)
|
onNavigateError(mapped)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> LogUtil.d(TAG, "Unhandled EmvResult Status : $status")
|
else -> LogUtil.d(TAG, "Unhandled EmvResult Status : $status")
|
||||||
|
|||||||
@ -1,139 +0,0 @@
|
|||||||
package com.mob.utsmyanmar.ui.error
|
|
||||||
|
|
||||||
import androidx.activity.compose.BackHandler
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
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.height
|
|
||||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.rounded.Check
|
|
||||||
import androidx.compose.material.icons.rounded.Close
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.mob.utsmyanmar.ui.preview.P2Preview
|
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
|
|
||||||
private const val AUTO_DISMISS_DELAY_MS = 3000L
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun TransactionErrorScreen(
|
|
||||||
isSuccess: Boolean,
|
|
||||||
message: String,
|
|
||||||
onDone: () -> Unit
|
|
||||||
) {
|
|
||||||
BackHandler(enabled = true) {
|
|
||||||
onDone()
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
delay(AUTO_DISMISS_DELAY_MS)
|
|
||||||
onDone()
|
|
||||||
}
|
|
||||||
|
|
||||||
TransactionErrorContent(isSuccess= isSuccess, message = message)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun TransactionErrorContent(isSuccess: Boolean,message: String) {
|
|
||||||
Scaffold(
|
|
||||||
containerColor = Color.IvoryBeige
|
|
||||||
) { paddingValues ->
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.background(Color.IvoryBeige)
|
|
||||||
.padding(paddingValues)
|
|
||||||
.statusBarsPadding()
|
|
||||||
.navigationBarsPadding()
|
|
||||||
.padding(horizontal = 20.dp),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
Spacer(modifier = Modifier.height(72.dp))
|
|
||||||
|
|
||||||
FailIcon(isSuccess)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = "Transaction Failed",
|
|
||||||
color = Color.LegacyRed,
|
|
||||||
style = MaterialTheme.typography.headlineLarge
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = message.ifBlank { "Something went wrong. Please try again." },
|
|
||||||
color = Color.Gray,
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
textAlign = TextAlign.Center
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun FailIcon(isSuccess: Boolean) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.size(132.dp),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.size(132.dp)
|
|
||||||
.background(
|
|
||||||
color = if (isSuccess) Color.Success.copy(alpha = 0.12f) else Color.Error.copy(alpha = 0.12f),
|
|
||||||
shape = CircleShape
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.size(96.dp)
|
|
||||||
.background(
|
|
||||||
color = if (isSuccess) Color.Success else Color.Error,
|
|
||||||
shape = CircleShape
|
|
||||||
),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
if(isSuccess) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.Check,
|
|
||||||
contentDescription = "Success",
|
|
||||||
tint = Color.White,
|
|
||||||
modifier = Modifier.size(64.dp)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.Close,
|
|
||||||
contentDescription = "Failed",
|
|
||||||
tint = Color.White,
|
|
||||||
modifier = Modifier.size(64.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@P2Preview
|
|
||||||
@Composable
|
|
||||||
private fun PreviewTransactionErrorScreen() {
|
|
||||||
TransactionErrorContent(isSuccess = true, message = "Reversal Success")
|
|
||||||
}
|
|
||||||
@ -74,7 +74,7 @@ private fun String.toTransactionConfig(): TransactionConfig {
|
|||||||
processCode = ProcessCode.PRE_AUTH_COMPLETE_VOID + ProcessCode.SMART + ProcessCode.TO_ACCOUNT
|
processCode = ProcessCode.PRE_AUTH_COMPLETE_VOID + ProcessCode.SMART + ProcessCode.TO_ACCOUNT
|
||||||
)
|
)
|
||||||
|
|
||||||
"cash adv" -> TransactionConfig(
|
"cash out" -> TransactionConfig(
|
||||||
transactionName = "CASH_OUT",
|
transactionName = "CASH_OUT",
|
||||||
transactionType = TransactionsType.CASH_OUT,
|
transactionType = TransactionsType.CASH_OUT,
|
||||||
processCode = ProcessCode.CASH_ADVANCE + ProcessCode.SMART + ProcessCode.TO_ACCOUNT
|
processCode = ProcessCode.CASH_ADVANCE + ProcessCode.SMART + ProcessCode.TO_ACCOUNT
|
||||||
|
|||||||
@ -56,13 +56,7 @@ fun InputAmount(
|
|||||||
val supportingText = "Enter the amount to continue"
|
val supportingText = "Enter the amount to continue"
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = { AppBar(title = "Amount", icon = Icons.AutoMirrored.Rounded.ArrowBack, onIconClick = onBackClick) },
|
||||||
AppBar(
|
|
||||||
title = "Amount",
|
|
||||||
icon = Icons.AutoMirrored.Rounded.ArrowBack,
|
|
||||||
onIconClick = onBackClick
|
|
||||||
)
|
|
||||||
},
|
|
||||||
containerColor = Color.IvoryBeige
|
containerColor = Color.IvoryBeige
|
||||||
) {paddingValues ->
|
) {paddingValues ->
|
||||||
|
|
||||||
@ -80,8 +74,7 @@ fun InputAmount(
|
|||||||
.weight(2f),
|
.weight(2f),
|
||||||
){
|
){
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier
|
modifier = Modifier.align(Alignment.CenterEnd)
|
||||||
.align(Alignment.CenterEnd)
|
|
||||||
.clickable(enabled = true) {
|
.clickable(enabled = true) {
|
||||||
amount = amount.dropLast(1)
|
amount = amount.dropLast(1)
|
||||||
},
|
},
|
||||||
@ -108,21 +101,29 @@ fun InputAmount(
|
|||||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
|
) {
|
||||||
|
if (prefixLabel.isNotBlank()) {
|
||||||
|
Text(
|
||||||
|
text = prefixLabel,
|
||||||
|
color = Color.LegacyRed,
|
||||||
|
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Medium),
|
||||||
|
modifier = Modifier.padding(end = 10.dp, bottom = 6.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = formatAmount(amount.ifEmpty { "0" }),
|
text = formatAmount(amount.ifEmpty { "0" }),
|
||||||
color = Color.LegacyRed,
|
color = Color.LegacyRed,
|
||||||
style = MaterialTheme.typography.displayLarge
|
style = MaterialTheme.typography.displayLarge
|
||||||
)
|
)
|
||||||
|
|
||||||
if (prefixLabel.isNotBlank()) {
|
|
||||||
Text(
|
|
||||||
text = prefixLabel,
|
|
||||||
color = Color.LegacyRed,
|
|
||||||
style = MaterialTheme.typography.displaySmall.copy(fontWeight = FontWeight.Medium),
|
|
||||||
modifier = Modifier.padding(end = 10.dp, bottom = 6.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(14.dp))
|
Spacer(modifier = Modifier.height(14.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = supportingText,
|
text = supportingText,
|
||||||
color = Color.Gray,
|
color = Color.Gray,
|
||||||
@ -131,6 +132,8 @@ fun InputAmount(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//second container
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -175,8 +178,7 @@ fun InputAmount(
|
|||||||
onClick = {
|
onClick = {
|
||||||
if (amount.isNotEmpty()) {
|
if (amount.isNotEmpty()) {
|
||||||
onChargeClick(amount)
|
onChargeClick(amount)
|
||||||
}
|
} },
|
||||||
},
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.height(56.dp),
|
.height(56.dp),
|
||||||
@ -234,15 +236,14 @@ private fun formatAmount(value: String): String {
|
|||||||
val groupedWholePart = "%,d".format(wholePart.toLongOrNull() ?: 0L)
|
val groupedWholePart = "%,d".format(wholePart.toLongOrNull() ?: 0L)
|
||||||
|
|
||||||
if (!normalized.contains(".")) {
|
if (!normalized.contains(".")) {
|
||||||
return "$groupedWholePart.00"
|
return groupedWholePart
|
||||||
}
|
}
|
||||||
|
|
||||||
val decimalPart = normalized.substringAfter(".", "")
|
val decimalPart = normalized.substringAfter(".", "")
|
||||||
return if (normalized.endsWith(".")) {
|
return if (normalized.endsWith(".")) {
|
||||||
"$groupedWholePart.00"
|
"$groupedWholePart."
|
||||||
} else {
|
} else {
|
||||||
val padded = decimalPart.padEnd(2, '0').take(2)
|
"$groupedWholePart.$decimalPart"
|
||||||
"$groupedWholePart.$padded"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import androidx.compose.ui.focus.FocusRequester
|
|||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.text.TextRange
|
import androidx.compose.ui.text.TextRange
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
@ -232,7 +233,8 @@ private fun ManualCardEntryScreen(
|
|||||||
singleLine = true,
|
singleLine = true,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
textStyle = MaterialTheme.typography.bodyLarge.copy(
|
textStyle = MaterialTheme.typography.bodyLarge.copy(
|
||||||
letterSpacing = 2.sp
|
letterSpacing = 2.sp,
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -261,7 +263,8 @@ private fun ManualCardEntryScreen(
|
|||||||
.width(160.dp)
|
.width(160.dp)
|
||||||
.focusRequester(expiryFocusRequester),
|
.focusRequester(expiryFocusRequester),
|
||||||
textStyle = MaterialTheme.typography.bodyLarge.copy(
|
textStyle = MaterialTheme.typography.bodyLarge.copy(
|
||||||
letterSpacing = 2.sp
|
letterSpacing = 2.sp,
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -281,6 +284,7 @@ private fun ManualCardEntryScreen(
|
|||||||
Text(
|
Text(
|
||||||
text = "**** **** **** ${pan.takeLast(4)}",
|
text = "**** **** **** ${pan.takeLast(4)}",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
fontFamily = FontFamily.Monospace,
|
||||||
letterSpacing = 1.5.sp
|
letterSpacing = 1.5.sp
|
||||||
)
|
)
|
||||||
if (expiry.length == 4) {
|
if (expiry.length == 4) {
|
||||||
|
|||||||
@ -91,7 +91,7 @@ fun AppNavGraph(
|
|||||||
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
||||||
SignaturePad(
|
SignaturePad(
|
||||||
onBack = { navController.popBackStack() },
|
onBack = { navController.popBackStack() },
|
||||||
onConfirm = { bitmap, signatureBlob ->
|
onConfirm = { _, bitmap, signatureBlob ->
|
||||||
sharedViewModel.signBitmap = bitmap
|
sharedViewModel.signBitmap = bitmap
|
||||||
sharedViewModel.updateSignatureBlob(signatureBlob)
|
sharedViewModel.updateSignatureBlob(signatureBlob)
|
||||||
navController.navigate(Routes.TransactionResult.route) {
|
navController.navigate(Routes.TransactionResult.route) {
|
||||||
@ -592,9 +592,9 @@ fun AppNavGraph(
|
|||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onNavigateError = { isSuccess,message ->
|
onNavigateError = { message ->
|
||||||
navController.navigate(Routes.TransactionError.createRoute(isSuccess,message)) {
|
navController.navigate(Routes.TransactionError.createRoute(message)) {
|
||||||
popUpTo(Routes.Processing.route) {
|
popUpTo(Routes.ProcessingCard.route) {
|
||||||
inclusive = true
|
inclusive = true
|
||||||
}
|
}
|
||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
@ -681,8 +681,8 @@ fun AppNavGraph(
|
|||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onNavigateError = { isSuccess,message ->
|
onNavigateError = { message ->
|
||||||
navController.navigate(Routes.TransactionError.createRoute(isSuccess,message)) {
|
navController.navigate(Routes.TransactionError.createRoute(message)) {
|
||||||
popUpTo(Routes.EmvTransaction.route) {
|
popUpTo(Routes.EmvTransaction.route) {
|
||||||
inclusive = true
|
inclusive = true
|
||||||
}
|
}
|
||||||
@ -764,8 +764,8 @@ fun AppNavGraph(
|
|||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onNavigateError = { isSuccess,message ->
|
onNavigateError = { message ->
|
||||||
navController.navigate(Routes.TransactionError.createRoute(isSuccess,message)) {
|
navController.navigate(Routes.TransactionError.createRoute(message)) {
|
||||||
popUpTo(Routes.Processing.route) {
|
popUpTo(Routes.Processing.route) {
|
||||||
inclusive = true
|
inclusive = true
|
||||||
}
|
}
|
||||||
@ -819,11 +819,9 @@ fun AppNavGraph(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
) { backStackEntry ->
|
) { backStackEntry ->
|
||||||
val isSuccess = backStackEntry.arguments?.getBoolean("isSuccess") ?: false
|
val message = backStackEntry.arguments?.getString("message").orEmpty().trim()
|
||||||
val message = backStackEntry.arguments?.getString("message").orEmpty()
|
|
||||||
|
|
||||||
TransactionErrorScreen(
|
TransactionErrorScreen(
|
||||||
isSuccess = isSuccess,
|
|
||||||
message = message,
|
message = message,
|
||||||
onDone = {
|
onDone = {
|
||||||
navController.navigate(Routes.Dashboard.route) {
|
navController.navigate(Routes.Dashboard.route) {
|
||||||
|
|||||||
@ -31,7 +31,10 @@ sealed class Routes(val route: String) {
|
|||||||
|
|
||||||
|
|
||||||
data object TransactionResult : Routes("transaction_result")
|
data object TransactionResult : Routes("transaction_result")
|
||||||
|
data object TransactionError : Routes("transaction_error/{message}") {
|
||||||
|
fun createRoute(message: String): String =
|
||||||
|
"transaction_error/${Uri.encode(message.ifBlank { " " })}"
|
||||||
|
}
|
||||||
data object PrintReceipt : Routes("print_receipt")
|
data object PrintReceipt : Routes("print_receipt")
|
||||||
data object Version : Routes("version")
|
data object Version : Routes("version")
|
||||||
data object Functions : Routes("functions")
|
data object Functions : Routes("functions")
|
||||||
@ -47,7 +50,4 @@ sealed class Routes(val route: String) {
|
|||||||
data object Disable : Routes("disable/{message}") {
|
data object Disable : Routes("disable/{message}") {
|
||||||
fun createRoute(message: String): String = "disable/${Uri.encode(message)}"
|
fun createRoute(message: String): String = "disable/${Uri.encode(message)}"
|
||||||
}
|
}
|
||||||
data object TransactionError : Routes("transaction_error/{isSuccess}/{message}") {
|
|
||||||
fun createRoute(isSuccess: Boolean, message: String): String = "transaction_error/$isSuccess/${Uri.encode(message)}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,29 +2,27 @@ package com.mob.utsmyanmar.ui.print_receipt
|
|||||||
|
|
||||||
import androidx.compose.animation.core.Animatable
|
import androidx.compose.animation.core.Animatable
|
||||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
|
import androidx.compose.animation.core.RepeatMode
|
||||||
|
import androidx.compose.animation.core.animateFloat
|
||||||
|
import androidx.compose.animation.core.infiniteRepeatable
|
||||||
|
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
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.*
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
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.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
@ -32,7 +30,10 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
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 androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
@ -43,15 +44,15 @@ import com.mob.utsmyanmar.ui.transaction_result.TransactionResultState
|
|||||||
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultViewModel
|
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 kotlin.math.abs
|
||||||
import kotlinx.coroutines.delay
|
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 const val PRINT_ANIMATION_DURATION_MS = 2300
|
||||||
MERCHANT("MERCHANT COPY"),
|
private const val RESET_ANIMATION_DURATION_MS = 350
|
||||||
CUSTOMER("CUSTOMER COPY")
|
private const val PRINTED_HOLD_DELAY_MS = 500L
|
||||||
}
|
private const val OFFSCREEN_BUFFER_PX = 120f
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PrintReceiptScreen(
|
fun PrintReceiptScreen(
|
||||||
@ -63,58 +64,9 @@ fun PrintReceiptScreen(
|
|||||||
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
|
var slotHeightPx by remember { mutableFloatStateOf(0f) }
|
||||||
val merchant_copy_autoprint = true
|
|
||||||
val customer_copy_autoprint = false
|
|
||||||
var currentCopy by remember { mutableStateOf(ReceiptCopy.MERCHANT) }
|
|
||||||
var nextCopy by remember { mutableStateOf(ReceiptCopy.CUSTOMER) }
|
|
||||||
var isPrinting by remember { mutableStateOf(false) }
|
var isPrinting by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
suspend fun animatePrint() {
|
|
||||||
receiptOffsetY.animateTo(
|
|
||||||
targetValue = -1500f,
|
|
||||||
animationSpec = tween(durationMillis = animationDuration, easing = FastOutSlowInEasing)
|
|
||||||
)
|
|
||||||
delay(1000.milliseconds)
|
|
||||||
receiptOffsetY.animateTo(
|
|
||||||
targetValue = 0f,
|
|
||||||
animationSpec = tween(durationMillis = 0, easing = FastOutSlowInEasing)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isReprintMode() = sharedViewModel.isReprint.value == true
|
|
||||||
|
|
||||||
fun doPrint(copy: ReceiptCopy, onFinished: () -> Unit) {
|
|
||||||
val reprint = isReprintMode()
|
|
||||||
val actualCopy = if (reprint && copy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else copy
|
|
||||||
currentCopy = actualCopy
|
|
||||||
sharedViewModel.setPrintStatus(
|
|
||||||
if (actualCopy == ReceiptCopy.MERCHANT) PrintStatus.FIRST_PRINT else PrintStatus.SECOND_PRINT
|
|
||||||
)
|
|
||||||
onPrint()
|
|
||||||
scope.launch {
|
|
||||||
isPrinting = true
|
|
||||||
animatePrint()
|
|
||||||
isPrinting = false
|
|
||||||
nextCopy = if (reprint) ReceiptCopy.CUSTOMER
|
|
||||||
else if (actualCopy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else ReceiptCopy.MERCHANT
|
|
||||||
onFinished()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
val reprint = isReprintMode()
|
|
||||||
if (reprint) {
|
|
||||||
currentCopy = ReceiptCopy.CUSTOMER
|
|
||||||
nextCopy = ReceiptCopy.CUSTOMER
|
|
||||||
}
|
|
||||||
sharedViewModel.isReprint.value = false
|
|
||||||
when {
|
|
||||||
merchant_copy_autoprint && !reprint -> doPrint(ReceiptCopy.MERCHANT) { }
|
|
||||||
customer_copy_autoprint -> doPrint(ReceiptCopy.CUSTOMER) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
AppBar(title = "Receipt")
|
AppBar(title = "Receipt")
|
||||||
@ -130,16 +82,41 @@ fun PrintReceiptScreen(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
ReceiptPreview(
|
Box(
|
||||||
state = state,
|
|
||||||
copyLabel = currentCopy.label,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.onSizeChanged { slotHeightPx = it.height.toFloat() }
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.clipToBounds()
|
||||||
|
) {
|
||||||
|
ReceiptPreview(
|
||||||
|
state = state,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
.graphicsLayer {
|
.graphicsLayer {
|
||||||
translationY = receiptOffsetY.value
|
translationY = receiptOffsetY.value
|
||||||
|
val travel = slotHeightPx + OFFSCREEN_BUFFER_PX
|
||||||
|
alpha = if (travel > 0f) {
|
||||||
|
1f - (abs(receiptOffsetY.value) / travel).coerceIn(0f, 1f)
|
||||||
|
} else {
|
||||||
|
1f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PrinterSlot(
|
||||||
|
isActive = isPrinting,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.TopCenter)
|
||||||
|
.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
@ -150,6 +127,7 @@ fun PrintReceiptScreen(
|
|||||||
|
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = onDone,
|
onClick = onDone,
|
||||||
|
enabled = !isPrinting,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.height(50.dp),
|
.height(50.dp),
|
||||||
@ -170,15 +148,50 @@ fun PrintReceiptScreen(
|
|||||||
containerColor = Color.LegacyRed,
|
containerColor = Color.LegacyRed,
|
||||||
contentColor = Color.White,
|
contentColor = Color.White,
|
||||||
disabledContainerColor = Color.LegacyRed.copy(alpha = 0.5f),
|
disabledContainerColor = Color.LegacyRed.copy(alpha = 0.5f),
|
||||||
disabledContentColor = Color.White.copy(alpha = 0.5f),
|
disabledContentColor = Color.White.copy(alpha = 0.7f),
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(12.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
doPrint(nextCopy) { }
|
if (isPrinting) return@Button
|
||||||
|
|
||||||
|
isPrinting = true
|
||||||
|
onPrint()
|
||||||
|
|
||||||
|
scope.launch {
|
||||||
|
val targetOffset = -(slotHeightPx + OFFSCREEN_BUFFER_PX)
|
||||||
|
|
||||||
|
receiptOffsetY.animateTo(
|
||||||
|
targetValue = targetOffset,
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = PRINT_ANIMATION_DURATION_MS,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
delay(PRINTED_HOLD_DELAY_MS)
|
||||||
|
|
||||||
|
receiptOffsetY.animateTo(
|
||||||
|
targetValue = 0f,
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = RESET_ANIMATION_DURATION_MS,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
isPrinting = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
if (isPrinting) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.size(18.dp),
|
||||||
|
color = Color.White,
|
||||||
|
strokeWidth = 2.dp
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
}
|
||||||
Text(
|
Text(
|
||||||
text = "Print",
|
text = if (isPrinting) "Printing..." else "Print",
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = MaterialTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -188,11 +201,52 @@ fun PrintReceiptScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visual "exit slot" pinned to the top of the receipt preview. The receipt
|
||||||
|
* appears to feed upward through this slot and out of frame while printing,
|
||||||
|
* mimicking a physical thermal printer.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
private fun PrinterSlot(
|
||||||
|
isActive: Boolean,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
val infiniteTransition = rememberInfiniteTransition(label = "printerSlotGlow")
|
||||||
|
val glow by infiniteTransition.animateFloat(
|
||||||
|
initialValue = 0.35f,
|
||||||
|
targetValue = 1f,
|
||||||
|
animationSpec = infiniteRepeatable(
|
||||||
|
animation = tween(durationMillis = 550, easing = FastOutSlowInEasing),
|
||||||
|
repeatMode = RepeatMode.Reverse
|
||||||
|
),
|
||||||
|
label = "glow"
|
||||||
|
)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = modifier,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 40.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(6.dp)
|
||||||
|
.clip(RoundedCornerShape(50))
|
||||||
|
.background(
|
||||||
|
if (isActive) {
|
||||||
|
Color.LegacyRed.copy(alpha = glow)
|
||||||
|
} else {
|
||||||
|
Color.Gray.copy(alpha = 0.25f)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReceiptPreview(
|
fun ReceiptPreview(
|
||||||
state: TransactionResultState,
|
state: TransactionResultState,
|
||||||
copyLabel: String,
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@ -210,18 +264,12 @@ fun ReceiptPreview(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "MOB POS",
|
text = "MOB POS",
|
||||||
style = MaterialTheme.typography.headlineLarge
|
style = MaterialTheme.typography.headlineLarge.copy(fontFamily = FontFamily.Monospace)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Transaction Receipt",
|
text = "Transaction Receipt",
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium.copy(fontFamily = FontFamily.Monospace)
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
Text(
|
|
||||||
text = copyLabel,
|
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
color = Color.Gray
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
ReceiptDivider()
|
ReceiptDivider()
|
||||||
@ -240,14 +288,14 @@ fun ReceiptPreview(
|
|||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Thank You",
|
text = "Thank You",
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = MaterialTheme.typography.titleMedium.copy(fontFamily = FontFamily.Monospace)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = "Please keep this receipt",
|
text = "Please keep this receipt",
|
||||||
style = MaterialTheme.typography.bodySmall
|
style = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,13 +313,13 @@ fun ReceiptRow(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = label,
|
text = label,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),
|
||||||
color = Color.Gray
|
color = Color.Gray
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = value,
|
text = value,
|
||||||
style = MaterialTheme.typography.titleSmall
|
style = MaterialTheme.typography.titleSmall.copy(fontFamily = FontFamily.Monospace)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,6 +331,7 @@ fun ReceiptDivider() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 10.dp),
|
.padding(vertical = 10.dp),
|
||||||
text = "--------------------------------",
|
text = "--------------------------------",
|
||||||
|
fontFamily = FontFamily.Monospace,
|
||||||
color = Color.Gray
|
color = Color.Gray
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ fun ProcessingCardRoute(
|
|||||||
onNavigateInputAmount: () -> Unit,
|
onNavigateInputAmount: () -> Unit,
|
||||||
onNavigateProcessing: () -> Unit,
|
onNavigateProcessing: () -> Unit,
|
||||||
onNavigateEmvTransaction: () -> Unit,
|
onNavigateEmvTransaction: () -> Unit,
|
||||||
onNavigateError: (isSuccess: Boolean, message: String) -> Unit,
|
onNavigateError: (String) -> Unit,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onShowDecline: (String) -> Unit
|
onShowDecline: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
@ -31,7 +31,7 @@ fun ProcessingCardRoute(
|
|||||||
ProcessingCardUiEvent.NavigateToInputAmount -> onNavigateInputAmount()
|
ProcessingCardUiEvent.NavigateToInputAmount -> onNavigateInputAmount()
|
||||||
ProcessingCardUiEvent.NavigateToProcessing -> onNavigateProcessing()
|
ProcessingCardUiEvent.NavigateToProcessing -> onNavigateProcessing()
|
||||||
ProcessingCardUiEvent.NavigateToEmvTransaction -> onNavigateEmvTransaction()
|
ProcessingCardUiEvent.NavigateToEmvTransaction -> onNavigateEmvTransaction()
|
||||||
is ProcessingCardUiEvent.NavigateToError -> onNavigateError(false,event.message)
|
is ProcessingCardUiEvent.NavigateToError -> onNavigateError(event.message)
|
||||||
is ProcessingCardUiEvent.ShowDeclineAndBack -> {
|
is ProcessingCardUiEvent.ShowDeclineAndBack -> {
|
||||||
onShowDecline(event.message)
|
onShowDecline(event.message)
|
||||||
onBack()
|
onBack()
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.mob.utsmyanmar.model.CardTransactionType
|
import com.mob.utsmyanmar.model.CardTransactionType
|
||||||
import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel
|
import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel
|
||||||
|
import com.mob.utsmyanmar.utils.MockCardData
|
||||||
import com.mob.utsmyanmar.utils.MockData
|
import com.mob.utsmyanmar.utils.MockData
|
||||||
import com.mob.utsmyanmar.utils.TransactionUtil
|
import com.mob.utsmyanmar.utils.TransactionUtil
|
||||||
import com.mob.utsmyanmar.viewmodel.CardReaderViewModel
|
import com.mob.utsmyanmar.viewmodel.CardReaderViewModel
|
||||||
|
|||||||
@ -25,7 +25,7 @@ fun ProcessingRoute(
|
|||||||
settlementViewModel: SettlementViewModel,
|
settlementViewModel: SettlementViewModel,
|
||||||
onNavigateTransactionResult: () -> Unit,
|
onNavigateTransactionResult: () -> Unit,
|
||||||
onNavigateSignature: () -> Unit,
|
onNavigateSignature: () -> Unit,
|
||||||
onNavigateError: (Boolean,String) -> Unit,
|
onNavigateError: (String) -> Unit,
|
||||||
onNavigateMain: ()-> Unit
|
onNavigateMain: ()-> Unit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ private fun EmvProcessingContent(
|
|||||||
sharedViewModel: SharedViewModel,
|
sharedViewModel: SharedViewModel,
|
||||||
emvTransactionViewModel: EmvTransactionProcessViewModel,
|
emvTransactionViewModel: EmvTransactionProcessViewModel,
|
||||||
onNavigateTransactionResult: () -> Unit,
|
onNavigateTransactionResult: () -> Unit,
|
||||||
onNavigateError: (Boolean,String) -> Unit,
|
onNavigateError: (String) -> Unit,
|
||||||
onNavigateMain: () -> Unit
|
onNavigateMain: () -> Unit
|
||||||
) {
|
) {
|
||||||
val emvTransStatus by emvTransactionViewModel.getTransStatus().observeAsState()
|
val emvTransStatus by emvTransactionViewModel.getTransStatus().observeAsState()
|
||||||
@ -134,13 +134,13 @@ private fun EmvProcessingContent(
|
|||||||
TransResultStatus.REVERSAL_SUCCESS -> {
|
TransResultStatus.REVERSAL_SUCCESS -> {
|
||||||
sharedViewModel.payDetail.value = emvTransactionViewModel.payDetailResult.value
|
sharedViewModel.payDetail.value = emvTransactionViewModel.payDetailResult.value
|
||||||
sharedViewModel.set_successFragmentMsg("Reversal success!")
|
sharedViewModel.set_successFragmentMsg("Reversal success!")
|
||||||
onNavigateError(true,"Reversal success!")
|
onNavigateMain()
|
||||||
}
|
}
|
||||||
|
|
||||||
TransResultStatus.REVERSAL_FAIL -> {
|
TransResultStatus.REVERSAL_FAIL -> {
|
||||||
sharedViewModel.payDetail.value = emvTransactionViewModel.payDetailResult.value
|
sharedViewModel.payDetail.value = emvTransactionViewModel.payDetailResult.value
|
||||||
sharedViewModel.set_errorFragmentMsg("Reversal failed!")
|
sharedViewModel.set_errorFragmentMsg("Reversal failed!")
|
||||||
onNavigateError(false,"Reversal failed!")
|
onNavigateError("Reversal failed!")
|
||||||
}
|
}
|
||||||
|
|
||||||
TransResultStatus.ERROR,
|
TransResultStatus.ERROR,
|
||||||
@ -149,7 +149,7 @@ private fun EmvProcessingContent(
|
|||||||
?.substringAfter(":")
|
?.substringAfter(":")
|
||||||
?.takeIf { it.isNotBlank() }
|
?.takeIf { it.isNotBlank() }
|
||||||
?: "Transaction error"
|
?: "Transaction error"
|
||||||
onNavigateError(false,message)
|
onNavigateError(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
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.border
|
import android.graphics.Paint
|
||||||
|
import androidx.compose.foundation.Canvas
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.gestures.detectDragGestures
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
@ -19,31 +24,84 @@ 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.mutableStateListOf
|
||||||
|
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.Modifier
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.geometry.Size
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Path
|
||||||
|
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
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 androidx.core.graphics.createBitmap
|
||||||
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 se.warting.signaturepad.SignaturePadAdapter
|
|
||||||
import se.warting.signaturepad.SignaturePadView
|
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
import android.graphics.Canvas as AndroidCanvas
|
||||||
|
import android.graphics.Path as AndroidPath
|
||||||
import com.mob.utsmyanmar.ui.theme.Color as AppColor
|
import com.mob.utsmyanmar.ui.theme.Color as AppColor
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SignaturePad(
|
fun SignaturePad(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
signatureColor: Color = Color.Black,
|
||||||
onBack: () -> Unit = {},
|
onBack: () -> Unit = {},
|
||||||
onConfirm: (Bitmap?, ByteArray?) -> Unit = { _, _ -> }
|
// signatureBlob is null for Digital mode (using stored signature) or when nothing was drawn
|
||||||
|
onConfirm: (SignatureMode, Bitmap?, signatureBlob: ByteArray?) -> Unit = { _, _, _ -> }
|
||||||
) {
|
) {
|
||||||
var signaturePadAdapter: SignaturePadAdapter? = null
|
val paths = remember { mutableStateListOf<List<Offset>>() }
|
||||||
|
val currentPath = remember { mutableStateListOf<Offset>() }
|
||||||
|
var selectedMode by remember { mutableStateOf(SignatureMode.Manual) }
|
||||||
|
var canvasSize by remember { mutableStateOf(Size.Zero) }
|
||||||
|
var strokeWidth = 6f
|
||||||
|
|
||||||
val scaledWidth = 300
|
fun clearSignature() {
|
||||||
|
paths.clear()
|
||||||
|
currentPath.clear()
|
||||||
|
}
|
||||||
|
|
||||||
fun scaleBitmap(source: Bitmap): Bitmap {
|
|
||||||
val ratio = scaledWidth.toFloat() / source.width
|
fun buildBitmap(): Bitmap? {
|
||||||
val height = (source.height * ratio).toInt()
|
if (selectedMode == SignatureMode.Digital) return null
|
||||||
return Bitmap.createScaledBitmap(source, scaledWidth, height, true)
|
if (paths.isEmpty() && currentPath.isEmpty()) return null
|
||||||
|
if (canvasSize.width <= 0f || canvasSize.height <= 0f) return null
|
||||||
|
|
||||||
|
val bitmap =
|
||||||
|
createBitmap(canvasSize.width.toInt(), canvasSize.height.toInt(), Bitmap.Config.RGB_565)
|
||||||
|
val canvas = AndroidCanvas(bitmap)
|
||||||
|
canvas.drawColor(android.graphics.Color.WHITE) // fill white background first
|
||||||
|
|
||||||
|
val paint = Paint().apply {
|
||||||
|
color = android.graphics.Color.BLACK
|
||||||
|
style = Paint.Style.STROKE
|
||||||
|
isAntiAlias = true
|
||||||
|
strokeCap = Paint.Cap.ROUND
|
||||||
|
strokeJoin = Paint.Join.ROUND
|
||||||
|
strokeWidth = 10f
|
||||||
|
}
|
||||||
|
|
||||||
|
fun drawStroke(points: List<Offset>) {
|
||||||
|
if (points.size < 2) return
|
||||||
|
val path = AndroidPath().apply {
|
||||||
|
moveTo(points.first().x, points.first().y)
|
||||||
|
for (index in 1 until points.size) {
|
||||||
|
lineTo(points[index].x, points[index].y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
}
|
||||||
|
|
||||||
|
paths.forEach(::drawStroke)
|
||||||
|
drawStroke(currentPath)
|
||||||
|
|
||||||
|
return bitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bitmapToBlob(bitmap: Bitmap): ByteArray {
|
fun bitmapToBlob(bitmap: Bitmap): ByteArray {
|
||||||
@ -69,20 +127,95 @@ fun SignaturePad(
|
|||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
) {
|
) {
|
||||||
SignaturePadView(
|
Box(
|
||||||
onReady = { signaturePadAdapter = it },
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(0.85f) // narrower than full width, adjust as needed
|
||||||
|
.height(180.dp) // fixed height instead of weight(1f)
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
|
.background(Color.White, RoundedCornerShape(16.dp))
|
||||||
|
.padding(12.dp)
|
||||||
|
.onSizeChanged { size ->
|
||||||
|
canvasSize = Size(size.width.toFloat(), size.height.toFloat())
|
||||||
|
}
|
||||||
|
.pointerInput(Unit) {
|
||||||
|
detectDragGestures(
|
||||||
|
onDragStart = { startOffset ->
|
||||||
|
currentPath.add(startOffset)
|
||||||
|
},
|
||||||
|
onDrag = { change, _ ->
|
||||||
|
change.consume()
|
||||||
|
currentPath.add(change.position)
|
||||||
|
},
|
||||||
|
onDragEnd = {
|
||||||
|
paths.add(currentPath.toList())
|
||||||
|
currentPath.clear()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Canvas(modifier = Modifier.fillMaxSize()) {
|
||||||
|
paths.forEach { points ->
|
||||||
|
if (points.size > 1) {
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(points.first().x, points.first().y)
|
||||||
|
for (i in 1 until points.size) {
|
||||||
|
lineTo(points[i].x, points[i].y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawPath(
|
||||||
|
path = path,
|
||||||
|
color = signatureColor,
|
||||||
|
style = Stroke(width = strokeWidth)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPath.size > 1) {
|
||||||
|
val path = Path().apply {
|
||||||
|
moveTo(currentPath.first().x, currentPath.first().y)
|
||||||
|
for (i in 1 until currentPath.size) {
|
||||||
|
lineTo(currentPath[i].x, currentPath[i].y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawPath(
|
||||||
|
path = path,
|
||||||
|
color = signatureColor,
|
||||||
|
style = Stroke(width = strokeWidth)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(200.dp)
|
.height(150.dp)
|
||||||
.border(width = 1.dp, color = AppColor.LegacyRed)
|
) {
|
||||||
|
SignatureModeOption(
|
||||||
|
title = "Manual Sign",
|
||||||
|
subtitle = "Customer signs on screen",
|
||||||
|
selected = selectedMode == SignatureMode.Manual,
|
||||||
|
onClick = { selectedMode = SignatureMode.Manual },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(12.dp))
|
||||||
|
|
||||||
|
SignatureModeOption(
|
||||||
|
title = "Digital Sign",
|
||||||
|
subtitle = "Use stored signature",
|
||||||
|
selected = selectedMode == SignatureMode.Digital,
|
||||||
|
onClick = { selectedMode = SignatureMode.Digital },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = { signaturePadAdapter?.clear() },
|
onClick = { clearSignature() },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.height(50.dp)
|
.height(50.dp)
|
||||||
@ -92,10 +225,13 @@ fun SignaturePad(
|
|||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
val rawBitmap = signaturePadAdapter?.getSignatureBitmap()
|
val bitmap = buildBitmap()
|
||||||
val bitmap = rawBitmap?.let { scaleBitmap(it) }
|
if (selectedMode == SignatureMode.Manual && bitmap == null) {
|
||||||
|
// nothing drawn yet on Manual mode — block confirm
|
||||||
|
return@Button
|
||||||
|
}
|
||||||
val signatureBlob = bitmap?.let { bitmapToBlob(it) }
|
val signatureBlob = bitmap?.let { bitmapToBlob(it) }
|
||||||
onConfirm(bitmap, signatureBlob)
|
onConfirm(selectedMode, bitmap, signatureBlob)
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
|
|||||||
@ -1,93 +1,74 @@
|
|||||||
package com.mob.utsmyanmar.ui.theme
|
package com.mob.utsmyanmar.ui.theme
|
||||||
|
|
||||||
import androidx.compose.ui.text.font.Font
|
|
||||||
import androidx.compose.material3.Typography
|
import androidx.compose.material3.Typography
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.mob.utsmyanmar.R
|
|
||||||
|
|
||||||
private val LibreBaskerville = FontFamily(
|
|
||||||
Font(R.font.libre_baskerville_regular, FontWeight.Normal)
|
|
||||||
)
|
|
||||||
|
|
||||||
val Typography = Typography(
|
val Typography = Typography(
|
||||||
displayLarge = TextStyle(
|
displayLarge = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 32.sp,
|
fontSize = 32.sp,
|
||||||
lineHeight = 40.sp,
|
lineHeight = 40.sp,
|
||||||
),
|
),
|
||||||
displayMedium = TextStyle(
|
displayMedium = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 30.sp,
|
fontSize = 30.sp,
|
||||||
lineHeight = 38.sp,
|
lineHeight = 38.sp,
|
||||||
),
|
),
|
||||||
headlineLarge = TextStyle(
|
headlineLarge = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 24.sp,
|
fontSize = 24.sp,
|
||||||
lineHeight = 32.sp,
|
lineHeight = 32.sp,
|
||||||
),
|
),
|
||||||
headlineMedium = TextStyle(
|
headlineMedium = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 20.sp,
|
fontSize = 20.sp,
|
||||||
lineHeight = 28.sp,
|
lineHeight = 28.sp,
|
||||||
),
|
),
|
||||||
titleLarge = TextStyle(
|
titleLarge = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
fontSize = 22.sp,
|
fontSize = 22.sp,
|
||||||
lineHeight = 28.sp,
|
lineHeight = 28.sp,
|
||||||
),
|
),
|
||||||
titleMedium = TextStyle(
|
titleMedium = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
fontSize = 18.sp,
|
fontSize = 18.sp,
|
||||||
lineHeight = 26.sp,
|
lineHeight = 26.sp,
|
||||||
),
|
),
|
||||||
titleSmall = TextStyle(
|
titleSmall = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
lineHeight = 20.sp,
|
lineHeight = 20.sp,
|
||||||
),
|
),
|
||||||
bodyLarge = TextStyle(
|
bodyLarge = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
lineHeight = 24.sp,
|
lineHeight = 24.sp,
|
||||||
letterSpacing = 0.5.sp
|
letterSpacing = 0.5.sp
|
||||||
),
|
),
|
||||||
bodyMedium = TextStyle(
|
bodyMedium = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
lineHeight = 20.sp,
|
lineHeight = 20.sp,
|
||||||
),
|
),
|
||||||
bodySmall = TextStyle(
|
bodySmall = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
lineHeight = 16.sp,
|
lineHeight = 16.sp,
|
||||||
),
|
),
|
||||||
labelLarge = TextStyle(
|
labelLarge = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
lineHeight = 20.sp,
|
lineHeight = 20.sp,
|
||||||
),
|
),
|
||||||
labelMedium = TextStyle(
|
labelMedium = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
lineHeight = 16.sp,
|
lineHeight = 16.sp,
|
||||||
),
|
),
|
||||||
labelSmall = TextStyle(
|
labelSmall = TextStyle(
|
||||||
fontFamily = LibreBaskerville,
|
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
lineHeight = 16.sp,
|
lineHeight = 16.sp,
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package com.mob.utsmyanmar.ui.tms_setup
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.content.edit
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.mob.utsmyanmar.model.sirius.SiriusResponse
|
import com.mob.utsmyanmar.model.sirius.SiriusResponse
|
||||||
@ -49,7 +48,7 @@ class TmsSetupViewModel @Inject constructor(
|
|||||||
private val emvParamOperation: EmvParamOperation,
|
private val emvParamOperation: EmvParamOperation,
|
||||||
@ApplicationContext private val context: Context
|
@ApplicationContext private val context: Context
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val TAG = TmsSetupViewModel::class.simpleName;
|
|
||||||
private val _uiState = MutableStateFlow(TmsSetupUiState())
|
private val _uiState = MutableStateFlow(TmsSetupUiState())
|
||||||
private val _dashboardUiState = MutableStateFlow(DashboardUiState())
|
private val _dashboardUiState = MutableStateFlow(DashboardUiState())
|
||||||
val uiState: StateFlow<TmsSetupUiState> = _uiState.asStateFlow()
|
val uiState: StateFlow<TmsSetupUiState> = _uiState.asStateFlow()
|
||||||
@ -145,27 +144,19 @@ class TmsSetupViewModel @Inject constructor(
|
|||||||
val ops = SystemParamsOperation.getInstance()
|
val ops = SystemParamsOperation.getInstance()
|
||||||
|
|
||||||
if (!ops.isActive) {
|
if (!ops.isActive) {
|
||||||
LogUtil.d(TAG, "isActive ${ops.isActive}")
|
|
||||||
val msg = ops.disabledMsg.takeIf { it.isNotEmpty() }
|
val msg = ops.disabledMsg.takeIf { it.isNotEmpty() }
|
||||||
?: "This terminal has been disabled. Please contact your administrator."
|
?: "This terminal has been disabled. Please contact your administrator."
|
||||||
_uiState.update {
|
_uiState.update { it.copy(isLoading = false) }
|
||||||
it.copy(
|
viewModelScope.launch { _navigateToDisable.emit(msg) }
|
||||||
isLoading = false,
|
|
||||||
isError = true,
|
|
||||||
isTerminalDisabled = true,
|
|
||||||
statusText = "Terminal Disabled",
|
|
||||||
errorMessage = msg
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val validity = TMSUtil.getInstance().checkParams()
|
val validity = TMSUtil.getInstance().checkParams()
|
||||||
if (validity.status == ValidityStatus.SUCCESS) {
|
if (validity.status == ValidityStatus.SUCCESS) {
|
||||||
context.getSharedPreferences("mobpos_prefs", Context.MODE_PRIVATE)
|
context.getSharedPreferences("mobpos_prefs", Context.MODE_PRIVATE)
|
||||||
.edit {
|
.edit()
|
||||||
putLong("last_sync_time", System.currentTimeMillis())
|
.putLong("last_sync_time", System.currentTimeMillis())
|
||||||
}
|
.apply()
|
||||||
_uiState.update { it.copy(isLoading = false, statusText = "Ready.") }
|
_uiState.update { it.copy(isLoading = false, statusText = "Ready.") }
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_onSyncCompleted.emit(Unit)
|
_onSyncCompleted.emit(Unit)
|
||||||
|
|||||||
@ -24,8 +24,6 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.mob.utsmyanmar.ui.preview.P2Preview
|
import com.mob.utsmyanmar.ui.preview.P2Preview
|
||||||
import com.mob.utsmyanmar.ui.theme.Color
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
import com.mob.utsmyanmar.utils.toFormattedDate
|
|
||||||
import com.mob.utsmyanmar.utils.toFormattedTime
|
|
||||||
import com.utsmyanmar.paylibs.model.PayDetail
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
import com.utsmyanmar.paylibs.print.PrintReceipt
|
import com.utsmyanmar.paylibs.print.PrintReceipt
|
||||||
import com.utsmyanmar.paylibs.utils.POSUtil
|
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||||
@ -84,8 +82,8 @@ fun TransactionResultScreen(
|
|||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
InfoCard(
|
InfoCard(
|
||||||
date = "${state.payDetail?.transDate?.toFormattedDate()}",
|
date = "26 May 2026",
|
||||||
time = "${state.payDetail?.transTime?.toFormattedTime()}",
|
time = "12:06 PM",
|
||||||
transactionId = state.payDetail?.referNo.toString()
|
transactionId = state.payDetail?.referNo.toString()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import com.mob.utsmyanmar.model.ecr.ECRResultStatus
|
|||||||
import com.mob.utsmyanmar.utils.CoreUtils
|
import com.mob.utsmyanmar.utils.CoreUtils
|
||||||
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||||
import com.utsmyanmar.baselib.emv.EmvParamOperation
|
import com.utsmyanmar.baselib.emv.EmvParamOperation
|
||||||
|
import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest
|
||||||
import com.utsmyanmar.ecr.ECRHelper
|
import com.utsmyanmar.ecr.ECRHelper
|
||||||
import com.utsmyanmar.ecr.ECRProcess
|
import com.utsmyanmar.ecr.ECRProcess
|
||||||
import com.utsmyanmar.ecr.data.model.TransactionsResp
|
import com.utsmyanmar.ecr.data.model.TransactionsResp
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
package com.mob.utsmyanmar.utils
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
fun String.toFormattedDate(): String {
|
|
||||||
val inputFormat = SimpleDateFormat("dd/MM/yy", Locale.ENGLISH)
|
|
||||||
val outputFormat = SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH)
|
|
||||||
val date = inputFormat.parse(this)
|
|
||||||
return outputFormat.format(date!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.toFormattedTime(): String {
|
|
||||||
val inputFormat = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
|
|
||||||
val outputFormat = SimpleDateFormat("hh:mm a", Locale.ENGLISH)
|
|
||||||
val time = inputFormat.parse(this)
|
|
||||||
return outputFormat.format(time!!)
|
|
||||||
}
|
|
||||||
@ -131,7 +131,7 @@ class TMSSetupsImpl : TMSSetups {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Properties
|
//Properties
|
||||||
for (prop in siriusProperty) {
|
for (prop in siriusProperty.orEmpty()) {
|
||||||
val name = prop.name
|
val name = prop.name
|
||||||
val data = prop.property
|
val data = prop.property
|
||||||
|
|
||||||
@ -221,7 +221,6 @@ class TMSSetupsImpl : TMSSetups {
|
|||||||
"speedup_contactless_enable" -> ops.setSpeedUpContactless(parseBoolean(data))
|
"speedup_contactless_enable" -> ops.setSpeedUpContactless(parseBoolean(data))
|
||||||
"manual_entry_pin_enable" -> ops.isManualEntryPinEnable = parseBoolean(data)
|
"manual_entry_pin_enable" -> ops.isManualEntryPinEnable = parseBoolean(data)
|
||||||
"cmhl_enabled" -> ops.setCMHLEnable(parseBoolean(data))
|
"cmhl_enabled" -> ops.setCMHLEnable(parseBoolean(data))
|
||||||
"mmqr_enable" -> ops.setMmqrStatus(parseBoolean(data))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ops.carouselUrls = imgUrls.joinToString(",")
|
ops.carouselUrls = imgUrls.joinToString(",")
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import android.os.Handler
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.Message
|
import android.os.Message
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import com.mob.utsmyanmar.model.TransResultStatus
|
|
||||||
import com.utsmyanmar.baselib.emv.EmvParamOperation
|
import com.utsmyanmar.baselib.emv.EmvParamOperation
|
||||||
import com.utsmyanmar.baselib.repo.Repository
|
import com.utsmyanmar.baselib.repo.Repository
|
||||||
import com.utsmyanmar.baselib.util.enums.EmvResultStatus
|
import com.utsmyanmar.baselib.util.enums.EmvResultStatus
|
||||||
@ -25,6 +24,7 @@ import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
|||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import sunmi.sunmiui.utils.LogUtil
|
import sunmi.sunmiui.utils.LogUtil
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import com.mob.utsmyanmar.model.TransResultStatus
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class EmvTransactionProcessViewModel @Inject constructor(
|
class EmvTransactionProcessViewModel @Inject constructor(
|
||||||
|
|||||||
@ -3,7 +3,6 @@ package com.mob.utsmyanmar.viewmodel
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.mob.utsmyanmar.model.TransResultStatus
|
import com.mob.utsmyanmar.model.TransResultStatus
|
||||||
import com.mob.utsmyanmar.ui.sending_to_host.ProcessingState
|
import com.mob.utsmyanmar.ui.sending_to_host.ProcessingState
|
||||||
import com.utsmyanmar.baselib.repo.Repository
|
import com.utsmyanmar.baselib.repo.Repository
|
||||||
@ -20,10 +19,8 @@ import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
|||||||
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
@ -213,11 +210,8 @@ class TransProcessViewModel @Inject constructor(
|
|||||||
TransResultStatus.REVERSAL_PREPARE
|
TransResultStatus.REVERSAL_PREPARE
|
||||||
|
|
||||||
_state.value = _state.value.copy("Preparing Reversal")
|
_state.value = _state.value.copy("Preparing Reversal")
|
||||||
viewModelScope.launch {
|
|
||||||
delay(10_000L)
|
|
||||||
callReversal(tradeData)
|
callReversal(tradeData)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(message: String) {
|
override fun onError(message: String) {
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="152.4dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="152.4"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path
|
|
||||||
android:pathData="M60.4,25.7h31.5v56.6h-31.5z"
|
|
||||||
android:fillColor="#FF5F00"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M62.4,54c0,-11 5.1,-21.5 13.7,-28.3c-15.6,-12.3 -38.3,-9.6 -50.6,6.1C13.3,47.4 16,70 31.7,82.3c13.1,10.3 31.4,10.3 44.5,0C67.5,75.5 62.4,65 62.4,54z"
|
|
||||||
android:fillColor="#EB001B"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M134.4,54c0,19.9 -16.1,36 -36,36c-8.1,0 -15.9,-2.7 -22.2,-7.7c15.6,-12.3 18.3,-34.9 6,-50.6c-1.8,-2.2 -3.8,-4.3 -6,-6c15.6,-12.3 38.3,-9.6 50.5,6.1C131.7,38.1 134.4,45.9 134.4,54z"
|
|
||||||
android:fillColor="#F79E1B"/>
|
|
||||||
</vector>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB |
File diff suppressed because one or more lines are too long
@ -1,18 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="800dp"
|
|
||||||
android:height="800dp"
|
|
||||||
android:viewportWidth="750"
|
|
||||||
android:viewportHeight="471">
|
|
||||||
<path
|
|
||||||
android:pathData="M278.2,334.23l33.36,-195.76h53.36l-33.38,195.76H278.2L278.2,334.23z"
|
|
||||||
android:fillColor="#0E4595"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M524.31,142.69c-10.57,-3.97 -27.14,-8.22 -47.82,-8.22c-52.72,0 -89.86,26.55 -90.18,64.6c-0.3,28.13 26.51,43.82 46.75,53.19c20.77,9.6 27.75,15.72 27.65,24.28c-0.13,13.12 -16.59,19.12 -31.92,19.12c-21.35,0 -32.7,-2.97 -50.22,-10.27l-6.88,-3.11l-7.49,43.82c12.46,5.47 35.51,10.2 59.44,10.44c56.09,0 92.5,-26.25 92.92,-66.88c0.2,-22.27 -14.02,-39.22 -44.8,-53.19c-18.65,-9.06 -30.07,-15.1 -29.95,-24.27c0,-8.14 9.67,-16.84 30.56,-16.84c17.45,-0.27 30.09,3.53 39.94,7.5l4.78,2.26L524.31,142.69"
|
|
||||||
android:fillColor="#0E4595"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M661.61,138.46h-41.23c-12.77,0 -22.33,3.49 -27.94,16.23l-79.24,179.4h56.03c0,0 9.16,-24.12 11.23,-29.42c6.12,0 60.56,0.08 68.34,0.08c1.6,6.85 6.49,29.33 6.49,29.33h49.51L661.61,138.46L661.61,138.46zM596.2,264.87c4.41,-11.28 21.26,-54.72 21.26,-54.72c-0.31,0.52 4.38,-11.33 7.07,-18.68l3.61,16.88c0,0 10.22,46.73 12.35,56.53h-44.29V264.87L596.2,264.87z"
|
|
||||||
android:fillColor="#0E4595"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M45.88,138.46L45.2,142.54C66.29,147.64 85.13,155.03 101.62,164.23L148.97,333.91L205.42,333.85L289.43,138.46L232.9,138.46L180.66,271.96L175.1,244.83C174.84,243.99 174.56,243.15 174.27,242.31L156.11,154.99C152.88,142.6 143.51,138.9 131.92,138.46L45.88,138.46z"
|
|
||||||
android:fillColor="#0e4595"/>
|
|
||||||
</vector>
|
|
||||||
Binary file not shown.
@ -1,7 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<style name="Theme.MOBPOS" parent="android:style/Theme.Material.Light.NoActionBar">
|
<style name="Theme.MOBPOS" parent="android:style/Theme.Material.Light.NoActionBar"/>
|
||||||
<item name="fontFamily">@font/libre_baskerville_regular</item>
|
|
||||||
<item name="android:fontFamily">@font/libre_baskerville_regular</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
</resources>
|
||||||
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<network-security-config>
|
|
||||||
|
|
||||||
<domain-config cleartextTrafficPermitted="true">
|
|
||||||
<domain includeSubdomains="true">posuat.myanmarorientalbank.com:5033</domain>
|
|
||||||
</domain-config>
|
|
||||||
|
|
||||||
</network-security-config>
|
|
||||||
@ -1,12 +1,17 @@
|
|||||||
package com.utsmyanmar.ecr
|
package com.utsmyanmar.ecr
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.utsmyanmar.ecr.data.ResultOf
|
import com.utsmyanmar.ecr.data.ResultOf
|
||||||
|
import com.utsmyanmar.ecr.data.TransType
|
||||||
import com.utsmyanmar.ecr.data.mapper.RequestTransMapper
|
import com.utsmyanmar.ecr.data.mapper.RequestTransMapper
|
||||||
import com.utsmyanmar.ecr.data.mapper.ResponseTransMapper
|
import com.utsmyanmar.ecr.data.mapper.ResponseTransMapper
|
||||||
import com.utsmyanmar.ecr.data.model.RequestTrans
|
import com.utsmyanmar.ecr.data.model.RequestTrans
|
||||||
|
import com.utsmyanmar.ecr.data.model.ResponseTrans
|
||||||
import com.utsmyanmar.ecr.data.model.Transactions
|
import com.utsmyanmar.ecr.data.model.Transactions
|
||||||
import com.utsmyanmar.ecr.data.model.TransactionsResp
|
import com.utsmyanmar.ecr.data.model.TransactionsResp
|
||||||
|
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
//@Keep
|
//@Keep
|
||||||
object ECRProcess {
|
object ECRProcess {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -503,7 +503,7 @@ public class ISOSocket {
|
|||||||
|
|
||||||
LogUtil.e(Constant.TAG, "E:" + e.toString());
|
LogUtil.e(Constant.TAG, "E:" + e.toString());
|
||||||
|
|
||||||
// closeSocket();
|
closeSocket();
|
||||||
if (isReversal) {
|
if (isReversal) {
|
||||||
listener.onError(Constant.REVERSAL);
|
listener.onError(Constant.REVERSAL);
|
||||||
// listener.onError(new ReversalException());
|
// listener.onError(new ReversalException());
|
||||||
@ -519,7 +519,7 @@ public class ISOSocket {
|
|||||||
@Override
|
@Override
|
||||||
public void onComplete() {
|
public void onComplete() {
|
||||||
LogUtil.d(Constant.TAG, "onComplete");
|
LogUtil.d(Constant.TAG, "onComplete");
|
||||||
// closeSocket();
|
closeSocket();
|
||||||
isReversal = false;
|
isReversal = false;
|
||||||
listener.onComplete();
|
listener.onComplete();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1189,11 +1189,10 @@ public class PrintReceipt {
|
|||||||
private void printSignature(Bitmap signatureBitmap) {
|
private void printSignature(Bitmap signatureBitmap) {
|
||||||
try {
|
try {
|
||||||
sunmiPrinterService.setAlignment(1, null);
|
sunmiPrinterService.setAlignment(1, null);
|
||||||
int targetHeight = 200;
|
if (signatureBitmap.getWidth() > 130) {
|
||||||
if (signatureBitmap.getHeight() > targetHeight) {
|
double size = 1.0 * signatureBitmap.getHeight() * 130 / signatureBitmap.getWidth();
|
||||||
double ratio = 1.0 * targetHeight / signatureBitmap.getHeight();
|
int newHeight = (int) size;
|
||||||
int newWidth = (int) (signatureBitmap.getWidth() * ratio);
|
signatureBitmap = BitmapUtils.scale(signatureBitmap, 130, newHeight);
|
||||||
signatureBitmap = BitmapUtils.scale(signatureBitmap, newWidth, targetHeight);
|
|
||||||
}
|
}
|
||||||
sunmiPrinterService.printBitmap(signatureBitmap, null);
|
sunmiPrinterService.printBitmap(signatureBitmap, null);
|
||||||
sunmiPrinterService.printText("\n", null);
|
sunmiPrinterService.printText("\n", null);
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public abstract class BaseXPrint {
|
|||||||
|
|
||||||
protected String currentTime;
|
protected String currentTime;
|
||||||
|
|
||||||
protected static final String typeface_name = "jetBrainsMonoRegular.ttf";
|
protected static final String typeface_name = "jbm_semibold.ttf";
|
||||||
protected static final String MPU_AID = "A0000004820000000001";
|
protected static final String MPU_AID = "A0000004820000000001";
|
||||||
|
|
||||||
protected static final String HOST_NAME_VM = "VISA/ MASTERCARD";
|
protected static final String HOST_NAME_VM = "VISA/ MASTERCARD";
|
||||||
@ -954,12 +954,6 @@ public abstract class BaseXPrint {
|
|||||||
if (signatureBlob != null && signatureBlob.length > 0) {
|
if (signatureBlob != null && signatureBlob.length > 0) {
|
||||||
Bitmap signatureBitmap = android.graphics.BitmapFactory.decodeByteArray(signatureBlob, 0, signatureBlob.length);
|
Bitmap signatureBitmap = android.graphics.BitmapFactory.decodeByteArray(signatureBlob, 0, signatureBlob.length);
|
||||||
if (signatureBitmap != null) {
|
if (signatureBitmap != null) {
|
||||||
int targetHeight = 200;
|
|
||||||
if (signatureBitmap.getHeight() > targetHeight) {
|
|
||||||
double ratio = 1.0 * targetHeight / signatureBitmap.getHeight();
|
|
||||||
int newWidth = (int) (signatureBitmap.getWidth() * ratio);
|
|
||||||
signatureBitmap = BitmapUtils.scale(signatureBitmap, newWidth, targetHeight);
|
|
||||||
}
|
|
||||||
sunmiPrinterService.printBitmap(signatureBitmap, innerResultCallback);
|
sunmiPrinterService.printBitmap(signatureBitmap, innerResultCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -368,7 +368,7 @@ public class TransactionsOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (transactionsType == TransactionsType.PRE_AUTH_VOID) {
|
} else if (transactionsType == TransactionsType.PRE_AUTH_VOID) {
|
||||||
// newPay.setCardType(oldPay.getCardType());
|
newPay.setCardType(oldPay.getCardType());
|
||||||
newPay.setCustomOrderNo(oldPay.getVoucherNo());
|
newPay.setCustomOrderNo(oldPay.getVoucherNo());
|
||||||
newPay.setReferNo(oldPay.getReferNo());
|
newPay.setReferNo(oldPay.getReferNo());
|
||||||
newPay.setCardInfo(oldPay.getCardInfo());
|
newPay.setCardInfo(oldPay.getCardInfo());
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
package com.utsmyanmar.paylibs.utils.core_utils;
|
package com.utsmyanmar.paylibs.utils.core_utils;
|
||||||
|
|
||||||
import static com.utsmyanmar.paylibs.utils.core_utils.SystemParamsSettings.TRANSACTION_MANAGER_KEY;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import sunmi.sunmiui.utils.LogUtil;
|
import sunmi.sunmiui.utils.LogUtil;
|
||||||
|
|
||||||
|
import static com.utsmyanmar.paylibs.utils.core_utils.SystemParamsSettings.TRANSACTION_MANAGER_KEY;
|
||||||
|
|
||||||
|
import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
|
||||||
|
|
||||||
public class SystemParamsOperation {
|
public class SystemParamsOperation {
|
||||||
|
|
||||||
public static final String TAG = "SystemParamsOperation";
|
public static final String TAG = "SystemParamsOperation";
|
||||||
@ -33,6 +33,54 @@ public class SystemParamsOperation {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* public void init(String serialNumStart,
|
||||||
|
String batchNumStart,
|
||||||
|
int purchaseOrderStyle,
|
||||||
|
int correctFrequency,
|
||||||
|
int transactionNumber,
|
||||||
|
boolean printNegative,
|
||||||
|
int nonConnection,
|
||||||
|
boolean stateSecret,
|
||||||
|
boolean shieldAuthorizationCard,
|
||||||
|
int nonConnectionChoice,
|
||||||
|
boolean eCashVisaExemption) {
|
||||||
|
SystemParamsSettings bean = getSystemParamsSettings();
|
||||||
|
bean.setSerialNum(serialNumStart);
|
||||||
|
bean.setBatchNumStart(batchNumStart);
|
||||||
|
bean.setPurchaseOrderStyle(purchaseOrderStyle);
|
||||||
|
bean.setCorrectFrequency(correctFrequency);
|
||||||
|
bean.setTransactionNumber(transactionNumber);
|
||||||
|
bean.setPrintNegative(printNegative);
|
||||||
|
bean.setNonConnection(nonConnection);
|
||||||
|
bean.setStateSecret(stateSecret);
|
||||||
|
bean.setShieldAuthorizationCard(shieldAuthorizationCard);
|
||||||
|
bean.setNonConnectionChoice(nonConnectionChoice);
|
||||||
|
bean.setCashVisaExemption(eCashVisaExemption);
|
||||||
|
saveSystemParamsSettings(bean);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*public boolean isDownloadParamsOnce() {
|
||||||
|
SystemParamsSettings params = getSystemParamsSettings();
|
||||||
|
return params.isDownloadParamsOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveDownloadParamsOnce(boolean downloadParamsOnce) {
|
||||||
|
SystemParamsSettings params = getSystemParamsSettings();
|
||||||
|
params.setDownloadParamsOnce(downloadParamsOnce);
|
||||||
|
saveSystemParamsSettings(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNeedDownLoadICParams() {
|
||||||
|
SystemParamsSettings params = getSystemParamsSettings();
|
||||||
|
return params.isNeedDownLoadICParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveNeedDownLoadICParams(boolean needDownLoadICParams) {
|
||||||
|
SystemParamsSettings params = getSystemParamsSettings();
|
||||||
|
params.setNeedDownLoadICParams(needDownLoadICParams);
|
||||||
|
saveSystemParamsSettings(params);
|
||||||
|
}*/
|
||||||
|
|
||||||
public boolean isInjectOnce(){
|
public boolean isInjectOnce(){
|
||||||
SystemParamsSettings params = getSystemParamsSettings();
|
SystemParamsSettings params = getSystemParamsSettings();
|
||||||
return params.isInjectOnce();
|
return params.isInjectOnce();
|
||||||
@ -43,6 +91,13 @@ public class SystemParamsOperation {
|
|||||||
params.setInjectOnce(injectOnce);
|
params.setInjectOnce(injectOnce);
|
||||||
saveSystemParamsSettings(params);
|
saveSystemParamsSettings(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set serial number
|
||||||
|
*
|
||||||
|
* @param serialNumber Starting serial number
|
||||||
|
*/
|
||||||
public void saveSerialNumber(String serialNumber) {
|
public void saveSerialNumber(String serialNumber) {
|
||||||
if (TextUtils.isEmpty(serialNumber)) {
|
if (TextUtils.isEmpty(serialNumber)) {
|
||||||
return;
|
return;
|
||||||
@ -51,6 +106,12 @@ public class SystemParamsOperation {
|
|||||||
params.setSerialNum(serialNumber);
|
params.setSerialNum(serialNumber);
|
||||||
saveSystemParamsSettings(params);
|
saveSystemParamsSettings(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set invoice number
|
||||||
|
*
|
||||||
|
* @param invoiceNumber Starting invoice number
|
||||||
|
*/
|
||||||
public void saveInvoiceNumber(String invoiceNumber) {
|
public void saveInvoiceNumber(String invoiceNumber) {
|
||||||
if (TextUtils.isEmpty(invoiceNumber)) {
|
if (TextUtils.isEmpty(invoiceNumber)) {
|
||||||
return;
|
return;
|
||||||
@ -59,6 +120,13 @@ public class SystemParamsOperation {
|
|||||||
params.setInvoiceNum(invoiceNumber);
|
params.setInvoiceNum(invoiceNumber);
|
||||||
saveSystemParamsSettings(params);
|
saveSystemParamsSettings(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set batch number
|
||||||
|
*
|
||||||
|
* @param batchNumber Starting batch number
|
||||||
|
*/
|
||||||
public void saveBatchNumber(String batchNumber) {
|
public void saveBatchNumber(String batchNumber) {
|
||||||
if (TextUtils.isEmpty(batchNumber)) {
|
if (TextUtils.isEmpty(batchNumber)) {
|
||||||
return;
|
return;
|
||||||
@ -68,6 +136,11 @@ public class SystemParamsOperation {
|
|||||||
saveSystemParamsSettings(params);
|
saveSystemParamsSettings(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serial number increment
|
||||||
|
*/
|
||||||
private void incrementSerialNum() {
|
private void incrementSerialNum() {
|
||||||
SystemParamsSettings params = getSystemParamsSettings();
|
SystemParamsSettings params = getSystemParamsSettings();
|
||||||
String currentSerialNum = params.getCurrentSerialNum();
|
String currentSerialNum = params.getCurrentSerialNum();
|
||||||
@ -99,6 +172,10 @@ public class SystemParamsOperation {
|
|||||||
params.setSerialNum(transNumFormat);
|
params.setSerialNum(transNumFormat);
|
||||||
saveSystemParamsSettings(params);
|
saveSystemParamsSettings(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice number increment
|
||||||
|
*/
|
||||||
private void incrementInvoiceNum() {
|
private void incrementInvoiceNum() {
|
||||||
SystemParamsSettings params = getSystemParamsSettings();
|
SystemParamsSettings params = getSystemParamsSettings();
|
||||||
String currentInvoiceNum = params.getCurrentInvoiceNum();
|
String currentInvoiceNum = params.getCurrentInvoiceNum();
|
||||||
@ -875,17 +952,6 @@ public class SystemParamsOperation {
|
|||||||
saveSystemParamsSettings(params);
|
saveSystemParamsSettings(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMmqrStatus(boolean status) {
|
|
||||||
SystemParamsSettings params = getSystemParamsSettings();
|
|
||||||
params.setMmqrEnabled(status);
|
|
||||||
saveSystemParamsSettings(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getMmqrStatus(){
|
|
||||||
SystemParamsSettings params = getSystemParamsSettings();
|
|
||||||
return params.getMmqrEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCMHLEnabled(){
|
public boolean isCMHLEnabled(){
|
||||||
SystemParamsSettings params = getSystemParamsSettings();
|
SystemParamsSettings params = getSystemParamsSettings();
|
||||||
return params.isCmhlEnabled();
|
return params.isCmhlEnabled();
|
||||||
|
|||||||
@ -38,7 +38,7 @@ public class SystemParamsSettings implements Serializable {
|
|||||||
|
|
||||||
private boolean checkExpSwitch = false;
|
private boolean checkExpSwitch = false;
|
||||||
|
|
||||||
// private String tmsAddress = "https://posmgmt.myanmarorientalbank.com/api/v1";
|
// private String tmsAddress = "http://posuat.myanmarorientalbank.com:5033";
|
||||||
private String tmsAddress = "https://sirius-nest.utsmyanmar.com/api/v1";
|
private String tmsAddress = "https://sirius-nest.utsmyanmar.com/api/v1";
|
||||||
// private String tmsAddress = "http://128.199.170.203";
|
// private String tmsAddress = "http://128.199.170.203";
|
||||||
|
|
||||||
@ -55,7 +55,6 @@ public class SystemParamsSettings implements Serializable {
|
|||||||
|
|
||||||
private String merchantName = "";
|
private String merchantName = "";
|
||||||
|
|
||||||
|
|
||||||
private String receiptHeader = "";
|
private String receiptHeader = "";
|
||||||
|
|
||||||
private String merchantAddress = "";
|
private String merchantAddress = "";
|
||||||
@ -233,7 +232,6 @@ public class SystemParamsSettings implements Serializable {
|
|||||||
private byte[] pik_value;
|
private byte[] pik_value;
|
||||||
|
|
||||||
private byte[] pik_kcv;
|
private byte[] pik_kcv;
|
||||||
private boolean mmqrEnabled;
|
|
||||||
|
|
||||||
protected String getSecHostName() {
|
protected String getSecHostName() {
|
||||||
return secHostName;
|
return secHostName;
|
||||||
@ -903,14 +901,6 @@ public class SystemParamsSettings implements Serializable {
|
|||||||
this.emvEnabled = emvEnabled;
|
this.emvEnabled = emvEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMmqrEnabled(boolean status) {
|
|
||||||
this.mmqrEnabled = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getMmqrEnabled(){
|
|
||||||
return mmqrEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* // 流水号起始
|
/* // 流水号起始
|
||||||
private String serialNum = Configs.getInstance().SERIAL_NUM();
|
private String serialNum = Configs.getInstance().SERIAL_NUM();
|
||||||
// 批次号起始
|
// 批次号起始
|
||||||
|
|||||||
@ -117,10 +117,7 @@ public class HostUtils {
|
|||||||
msgType = MessageType.AUTHORIZATION;
|
msgType = MessageType.AUTHORIZATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PRE_AUTH_VOID:
|
|
||||||
case PRE_AUTH_COMPLETE:
|
case PRE_AUTH_COMPLETE:
|
||||||
if (hostName == HostName.BPC) {
|
if (hostName == HostName.BPC) {
|
||||||
msgType = MessageType.FINANCIAL;
|
msgType = MessageType.FINANCIAL;
|
||||||
@ -145,11 +142,11 @@ public class HostUtils {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case VOID:
|
case VOID:
|
||||||
|
case PRE_AUTH_VOID:
|
||||||
if(isVisaMaster) {
|
if(isVisaMaster) {
|
||||||
msgType = MessageType.REVERSAL;
|
msgType = MessageType.REVERSAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
msgType = MessageType.FINANCIAL;
|
msgType = MessageType.FINANCIAL;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -198,8 +198,7 @@ public class BitmapConfig {
|
|||||||
public static final String CZ_REVERSAL="7020078000C08000";
|
public static final String CZ_REVERSAL="7020078000C08000";
|
||||||
public static final String CZ_BATCH_UPLOAD="703805800CC00010";
|
public static final String CZ_BATCH_UPLOAD="703805800CC00010";
|
||||||
public static final String CZ_PRE_AUTH="7020058020C09000";
|
public static final String CZ_PRE_AUTH="7020058020C09000";
|
||||||
// public static final String CZ_PRE_AUTH_VOID="7038058028C08000";
|
public static final String CZ_PRE_AUTH_VOID="7038058028C08000";
|
||||||
public static final String CZ_PRE_AUTH_VOID="703C058008C08000";
|
|
||||||
public static final String CZ_PRE_AUTH_COMP="703805802CC08000";
|
public static final String CZ_PRE_AUTH_COMP="703805802CC08000";
|
||||||
public static final String CZ_PRE_AUTH_COMP_VOID="7038058008C00000";
|
public static final String CZ_PRE_AUTH_COMP_VOID="7038058008C00000";
|
||||||
|
|
||||||
|
|||||||
@ -361,12 +361,7 @@ public class FieldUtils {
|
|||||||
// } else {
|
// } else {
|
||||||
// iterator.remove();
|
// iterator.remove();
|
||||||
// }
|
// }
|
||||||
if(payDetail.getTransactionType() == REVERSAL.value) {
|
|
||||||
field.setDataStr("001");
|
|
||||||
} else {
|
|
||||||
field.setDataStr("000");
|
field.setDataStr("000");
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 24: //Network International Identifier NII
|
case 24: //Network International Identifier NII
|
||||||
|
|
||||||
@ -381,10 +376,10 @@ public class FieldUtils {
|
|||||||
08 – mail order/telephone order
|
08 – mail order/telephone order
|
||||||
* */
|
* */
|
||||||
// Service point condition code Fill in 00 for ordinary consumer transactions and mobile phone chip transactions, fill in 08 for order consumer transactions, fill in 64 for installment transactions, fill in 65 for points consumption transactions, fill in 67 for mobile phone card-free reservations
|
// Service point condition code Fill in 00 for ordinary consumer transactions and mobile phone chip transactions, fill in 08 for order consumer transactions, fill in 64 for installment transactions, fill in 65 for points consumption transactions, fill in 67 for mobile phone card-free reservations
|
||||||
// do not remove double check for preauth, it's control for reversal
|
if (payDetail.getTransactionType() == PRE_AUTH_SALE.value) {
|
||||||
if (payDetail.getTransactionType() == PRE_AUTH_SALE.value || payDetail.getTransType().equals(PRE_AUTH_SALE.name)) {
|
|
||||||
field.setDataStr("06");
|
field.setDataStr("06");
|
||||||
} else if(payDetail.getTransactionType() == REFUND.value || payDetail.getTransType().equals(REFUND.name) ) {
|
}
|
||||||
|
else if(payDetail.getTransactionType() == REFUND.value || payDetail.getTransactionType() == REVERSAL.value) {
|
||||||
// field.setDataStr("00"); // MPU
|
// field.setDataStr("00"); // MPU
|
||||||
field.setDataStr("61"); // CZ
|
field.setDataStr("61"); // CZ
|
||||||
} else if(payDetail.getCardType() == -1) {
|
} else if(payDetail.getCardType() == -1) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user