Compare commits
4 Commits
2323562270
...
43c903c9ee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43c903c9ee | ||
|
|
23a4ebfb64 | ||
|
|
962bfbc6c5 | ||
|
|
2093fb214a |
@ -40,8 +40,8 @@ android {
|
|||||||
dimension = "env"
|
dimension = "env"
|
||||||
applicationIdSuffix = ".uat"
|
applicationIdSuffix = ".uat"
|
||||||
versionNameSuffix = "-UAT"
|
versionNameSuffix = "-UAT"
|
||||||
versionCode = 17
|
versionCode = 19
|
||||||
versionName = "3.5"
|
versionName = "3.7"
|
||||||
buildConfigField("String", "ENV", "\"UAT\"")
|
buildConfigField("String", "ENV", "\"UAT\"")
|
||||||
resValue("string", "app_name", "MOB-UAT")
|
resValue("string", "app_name", "MOB-UAT")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,3 +19,18 @@
|
|||||||
* show reversal status in trans records
|
* show reversal status in trans records
|
||||||
* error_slip_print enable/disable in tms
|
* error_slip_print enable/disable in tms
|
||||||
* auto_settlement enable/disable in tms
|
* auto_settlement enable/disable in tms
|
||||||
|
|
||||||
|
### version 3.5
|
||||||
|
* "always with you" in mob receipt logo
|
||||||
|
* "..." full width in both P2 and P3 preview screens
|
||||||
|
* JCB logo added in Card Capture Screen
|
||||||
|
* "-" in void, refund and cash adv amounts
|
||||||
|
* disable sale button if amount is 0 or 0.00
|
||||||
|
* changed date formats to dd/mm/yy to dd/mm/yyyy
|
||||||
|
* changed keyboard design in reprint any transactions
|
||||||
|
|
||||||
|
### version 3.6
|
||||||
|
* qr for user manual
|
||||||
|
|
||||||
|
### version 3.7
|
||||||
|
* auto-settlement for both P2 and P3
|
||||||
@ -23,6 +23,7 @@
|
|||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
@ -43,6 +44,11 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.MOBPOS">
|
android:theme="@style/Theme.MOBPOS">
|
||||||
<receiver android:name=".auto_settlement.AlarmReceiver" android:exported="false"/>
|
<receiver android:name=".auto_settlement.AlarmReceiver" android:exported="false"/>
|
||||||
|
<receiver android:name=".auto_settlement.BootReceiver" android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
<service android:name=".auto_settlement.AutoSettleService" android:exported="false" android:foregroundServiceType="dataSync" />
|
<service android:name=".auto_settlement.AutoSettleService" android:exported="false" android:foregroundServiceType="dataSync" />
|
||||||
<activity
|
<activity
|
||||||
android:name="com.mob.utsmyanmar.MainActivity"
|
android:name="com.mob.utsmyanmar.MainActivity"
|
||||||
|
|||||||
@ -75,7 +75,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
private fun scheduleSettlementAlarm() {
|
private fun scheduleSettlementAlarm() {
|
||||||
if (!SystemParamsOperation.getInstance().isAutoSettlement()) {
|
if (!SystemParamsOperation.getInstance().isAutoSettlement()) {
|
||||||
SettlementScheduler.schedule(this)
|
SettlementScheduler.cancel(this)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +91,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
SettlementScheduler.scheduleFallback(this)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.mob.utsmyanmar.auto_settlement
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import sunmi.sunmiui.utils.LogUtil
|
||||||
|
|
||||||
|
class BootReceiver : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
if (intent?.action != Intent.ACTION_BOOT_COMPLETED) return
|
||||||
|
val appContext = context ?: return
|
||||||
|
|
||||||
|
LogUtil.d(BootReceiver::class.java.simpleName, "Boot completed, rescheduling settlement alarm")
|
||||||
|
SettlementScheduler.schedule(appContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ import java.util.Calendar
|
|||||||
|
|
||||||
object SettlementScheduler {
|
object SettlementScheduler {
|
||||||
private const val FALLBACK_ALERT_TIME = "23:30:00"
|
private const val FALLBACK_ALERT_TIME = "23:30:00"
|
||||||
|
private const val REQUEST_CODE = 100
|
||||||
|
|
||||||
fun schedule(context: Context): Boolean {
|
fun schedule(context: Context): Boolean {
|
||||||
if (!SystemParamsOperation.getInstance().isAutoSettlement()) {
|
if (!SystemParamsOperation.getInstance().isAutoSettlement()) {
|
||||||
@ -24,15 +25,49 @@ object SettlementScheduler {
|
|||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
|
||||||
!alarmManager.canScheduleExactAlarms()
|
!alarmManager.canScheduleExactAlarms()
|
||||||
) {
|
) {
|
||||||
|
return scheduleFallback(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
val calendar = nextAlarmCalendar() ?: return false
|
||||||
|
val pendingIntent = alarmPendingIntent(context)
|
||||||
|
|
||||||
|
alarmManager.setExactAndAllowWhileIdle(
|
||||||
|
AlarmManager.RTC_WAKEUP,
|
||||||
|
calendar.timeInMillis,
|
||||||
|
pendingIntent
|
||||||
|
)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scheduleFallback(context: Context): Boolean {
|
||||||
|
if (!SystemParamsOperation.getInstance().isAutoSettlement()) {
|
||||||
|
cancel(context)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val configuredTime = parseTime(
|
val alarmManager =
|
||||||
// SystemParamsOperation.getInstance().clearBatchTime
|
context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
"21:35:00"
|
|
||||||
) ?: parseTime(FALLBACK_ALERT_TIME)!!
|
|
||||||
|
|
||||||
val calendar = Calendar.getInstance().apply {
|
val calendar = nextAlarmCalendar() ?: return false
|
||||||
|
val pendingIntent = alarmPendingIntent(context)
|
||||||
|
|
||||||
|
alarmManager.setAndAllowWhileIdle(
|
||||||
|
AlarmManager.RTC_WAKEUP,
|
||||||
|
calendar.timeInMillis,
|
||||||
|
pendingIntent
|
||||||
|
)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun nextAlarmCalendar(): Calendar? {
|
||||||
|
val configuredTime = parseTime(
|
||||||
|
SystemParamsOperation.getInstance().clearBatchTime
|
||||||
|
// "15:45:00"
|
||||||
|
) ?: parseTime(FALLBACK_ALERT_TIME) ?: return null
|
||||||
|
|
||||||
|
return Calendar.getInstance().apply {
|
||||||
set(Calendar.HOUR_OF_DAY, configuredTime.first)
|
set(Calendar.HOUR_OF_DAY, configuredTime.first)
|
||||||
set(Calendar.MINUTE, configuredTime.second)
|
set(Calendar.MINUTE, configuredTime.second)
|
||||||
set(Calendar.SECOND, configuredTime.third)
|
set(Calendar.SECOND, configuredTime.third)
|
||||||
@ -42,30 +77,18 @@ object SettlementScheduler {
|
|||||||
add(Calendar.DAY_OF_MONTH, 1)
|
add(Calendar.DAY_OF_MONTH, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun alarmPendingIntent(context: Context): PendingIntent {
|
||||||
|
val intent = Intent(context, AlarmReceiver::class.java)
|
||||||
|
|
||||||
val intent = Intent(
|
return PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
AlarmReceiver::class.java
|
REQUEST_CODE,
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
val pendingIntent = PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
100,
|
|
||||||
intent,
|
intent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or
|
PendingIntent.FLAG_UPDATE_CURRENT or
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
PendingIntent.FLAG_IMMUTABLE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
alarmManager.setExactAndAllowWhileIdle(
|
|
||||||
AlarmManager.RTC_WAKEUP,
|
|
||||||
calendar.timeInMillis,
|
|
||||||
pendingIntent
|
|
||||||
)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseTime(value: String): Triple<Int, Int, Int>? {
|
private fun parseTime(value: String): Triple<Int, Int, Int>? {
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package com.mob.utsmyanmar.ui.dashboard
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import androidmads.library.qrgenearator.QRGContents
|
||||||
|
import androidmads.library.qrgenearator.QRGEncoder
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@ -46,6 +48,7 @@ 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.graphics.asImageBitmap
|
||||||
import androidx.compose.ui.layout.ContentScale
|
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
|
||||||
@ -264,7 +267,7 @@ fun DashboardScreen2(
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Released on : 21-Jul-26",
|
text = "Released on : 06-Sep-2026",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = Color.Gray,
|
color = Color.Gray,
|
||||||
modifier = Modifier.padding(horizontal = 16.dp)
|
modifier = Modifier.padding(horizontal = 16.dp)
|
||||||
@ -359,6 +362,38 @@ fun DashboardScreen2(
|
|||||||
trailingIcon = {},
|
trailingIcon = {},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
val adUrl = "https://www.mobmyanmar.com/"
|
||||||
|
val qrBitmap = remember {
|
||||||
|
runCatching {
|
||||||
|
val encoder = QRGEncoder(adUrl, null, QRGContents.Type.TEXT, 256)
|
||||||
|
encoder.colorBlack = android.graphics.Color.BLACK
|
||||||
|
encoder.colorWhite = android.graphics.Color.WHITE
|
||||||
|
encoder.bitmap.asImageBitmap()
|
||||||
|
}.getOrNull()
|
||||||
|
}
|
||||||
|
qrBitmap?.let { bitmap ->
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
bitmap = bitmap,
|
||||||
|
contentDescription = "Scan for User Guide",
|
||||||
|
modifier = Modifier.size(150.dp)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = "Scan for Offers",
|
||||||
|
style = MaterialTheme.typography.labelSmall,
|
||||||
|
color = Color.Gray
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Text(
|
Text(
|
||||||
text = "v${BuildConfig.VERSION_NAME}",
|
text = "v${BuildConfig.VERSION_NAME}",
|
||||||
|
|||||||
@ -436,7 +436,14 @@ fun AppNavGraph(
|
|||||||
SettlementScreen(
|
SettlementScreen(
|
||||||
sharedViewModel = sharedViewModel,
|
sharedViewModel = sharedViewModel,
|
||||||
settlementViewMode = settlementViewMode,
|
settlementViewMode = settlementViewMode,
|
||||||
onBack = { navController.popBackStack(Routes.Dashboard.route,false) },
|
onBack = {
|
||||||
|
onAutoSettlementHandled()
|
||||||
|
if (!navController.popBackStack(Routes.Dashboard.route, false)) {
|
||||||
|
navController.navigate(Routes.Dashboard.route) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
autoStartSettlement = autoSettlementRequested,
|
autoStartSettlement = autoSettlementRequested,
|
||||||
onStartSettlement = {
|
onStartSettlement = {
|
||||||
sharedViewModel.transactionsType.value = TransactionsType.SETTLEMENT
|
sharedViewModel.transactionsType.value = TransactionsType.SETTLEMENT
|
||||||
|
|||||||
@ -87,19 +87,21 @@ fun TransactionResultScreen(
|
|||||||
transactionId = state.payDetail?.referNo.toString()
|
transactionId = state.payDetail?.referNo.toString()
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
if (!state.isSuccess) {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = onContinue,
|
onClick = onContinue,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(56.dp),
|
.height(56.dp),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = Color.LegacyRed,
|
containerColor = Color.LegacyRed,
|
||||||
contentColor = Color.White
|
contentColor = Color.White
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text("Continue")
|
Text("Continue")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,5 +6,6 @@ data class TransactionResultState(
|
|||||||
val title: String = "Transaction Result",
|
val title: String = "Transaction Result",
|
||||||
val message: String = "",
|
val message: String = "",
|
||||||
val isLoading: Boolean = false,
|
val isLoading: Boolean = false,
|
||||||
|
val isSuccess: Boolean = false,
|
||||||
val payDetail: PayDetail? = null
|
val payDetail: PayDetail? = null
|
||||||
)
|
)
|
||||||
|
|||||||
@ -113,7 +113,8 @@ class TransactionResultViewModel @Inject constructor(
|
|||||||
|
|
||||||
_state.value = _state.value.copy(
|
_state.value = _state.value.copy(
|
||||||
title = title,
|
title = title,
|
||||||
message = message
|
message = message,
|
||||||
|
isSuccess = isSuccess
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -895,16 +895,16 @@ public abstract class BaseXPrint {
|
|||||||
try {
|
try {
|
||||||
sunmiPrinterService.setFontSize(18, innerResultCallback);
|
sunmiPrinterService.setFontSize(18, innerResultCallback);
|
||||||
sunmiPrinterService.setAlignment(0, innerResultCallback);
|
sunmiPrinterService.setAlignment(0, innerResultCallback);
|
||||||
sunmiPrinterService.printColumnsString(new String[]{"DATE :" + PrintUtils.getInstance().toFullYearDate(payDetail.getTransDate()), "TIME: " + payDetail.getTransTime()}, new int[]{2, 2}, new int[]{0, 2}, innerResultCallback);
|
sunmiPrinterService.printColumnsString(new String[]{"DATE :" + PrintUtils.getInstance().toFullYearDate(payDetail.getTransDate()), "TIME:" + payDetail.getTransTime()}, new int[]{2, 2}, new int[]{0, 2}, innerResultCallback);
|
||||||
if (payDetail.getTransactionType() == TransactionsType.WAVEPAY.value && payDetail.getQrTransStatus() == 1) {
|
if (payDetail.getTransactionType() == TransactionsType.WAVEPAY.value && payDetail.getQrTransStatus() == 1) {
|
||||||
sunmiPrinterService.printColumnsString(new String[]{"TRACE NO :" + traceNum, "INV NO: " + invoiceNo}, new int[]{2, 2}, new int[]{0, 2}, innerResultCallback);
|
sunmiPrinterService.printColumnsString(new String[]{"TRC NO:" + traceNum, "INV NO: " + invoiceNo}, new int[]{2, 2}, new int[]{0, 2}, innerResultCallback);
|
||||||
} else if (!payDetail.getTransType().equals(SETTLEMENT) && !payDetail.getTransType().equals(SUMMARY) && payDetail.getTransactionType() != TransactionsType.WAVEPAY_REFUND.value && payDetail.getTransactionType() != TransactionsType.WAVEPAY.value) {
|
} else if (!payDetail.getTransType().equals(SETTLEMENT) && !payDetail.getTransType().equals(SUMMARY) && payDetail.getTransactionType() != TransactionsType.WAVEPAY_REFUND.value && payDetail.getTransactionType() != TransactionsType.WAVEPAY.value) {
|
||||||
sunmiPrinterService.printColumnsString(new String[]{"BTH NO :" + batchNum, "INV NO: " + invoiceNo}, new int[]{2, 2}, new int[]{0, 2}, innerResultCallback);
|
sunmiPrinterService.printColumnsString(new String[]{"BTH NO:" + batchNum, "INV NO: " + invoiceNo}, new int[]{2, 2}, new int[]{0, 2}, innerResultCallback);
|
||||||
} else if (payDetail.getTransType().equals(SUMMARY)) {
|
} else if (payDetail.getTransType().equals(SUMMARY)) {
|
||||||
sunmiPrinterService.printColumnsString(new String[]{"HOST :" + HOST_NAME_MPU, ""}, new int[]{2, 1}, new int[]{0, 2}, innerResultCallback);
|
sunmiPrinterService.printColumnsString(new String[]{"HOST :" + HOST_NAME_MPU, ""}, new int[]{2, 1}, new int[]{0, 2}, innerResultCallback);
|
||||||
}
|
}
|
||||||
sunmiPrinterService.printText("MID :"+payDetail.getMerchantNo()+"\n",innerResultCallback);
|
sunmiPrinterService.printText("MID :"+payDetail.getMerchantNo()+"\n",innerResultCallback);
|
||||||
sunmiPrinterService.printText("TID :"+payDetail.getTerminalNo()+"\n",innerResultCallback);
|
sunmiPrinterService.printText("TID :"+payDetail.getTerminalNo()+"\n",innerResultCallback);
|
||||||
sunmiPrinterService.lineWrap(1, innerResultCallback);
|
sunmiPrinterService.lineWrap(1, innerResultCallback);
|
||||||
sunmiPrinterService.sendRAWData(boldOn(), innerResultCallback);
|
sunmiPrinterService.sendRAWData(boldOn(), innerResultCallback);
|
||||||
sunmiPrinterService.setAlignment(1, innerResultCallback);
|
sunmiPrinterService.setAlignment(1, innerResultCallback);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user