Compare commits

...

2 Commits

10 changed files with 443 additions and 231 deletions

View File

@ -31,6 +31,11 @@
<!-- Permission for exact alarms on Android 12+ --> <!-- Permission for exact alarms on Android 12+ -->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<!-- Permissions for background auto settlement -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<!-- android:noHistory="true"--> <!-- android:noHistory="true"-->
<!-- android:excludeFromRecents="true"--> <!-- android:excludeFromRecents="true"-->

View File

@ -455,8 +455,8 @@ public class MainActivity extends AppCompatActivity implements
payDetail.setAmount(totalAmount); payDetail.setAmount(totalAmount);
payDetail.setTradeAnswerCode("000"); payDetail.setTradeAnswerCode("000");
// Note: QR transactions list is not passed to avoid serialization issues
// The settlement summary is sufficient for the receipt sharedViewModel.setAmount(POSUtil.getInstance().getDecimalAmountSeparatorFormat(totalAmount));
sharedViewModel.payDetails.setValue(qrTransList); sharedViewModel.payDetails.setValue(qrTransList);
sharedViewModel.payDetail.setValue(payDetail); sharedViewModel.payDetail.setValue(payDetail);
sharedViewModel.transactionsType.setValue(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT); sharedViewModel.transactionsType.setValue(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT);

View File

@ -238,7 +238,7 @@ public class MainFragment extends DataBindingFragment {
sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus()); sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus());
generateMockQR(); // generateMockQR();
} }
/* /*

View File

@ -1,11 +1,17 @@
package com.utsmm.kbz.service; package com.utsmm.kbz.service;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.PowerManager;
import androidx.core.app.NotificationCompat;
import com.utsmm.kbz.R;
import com.utsmyanmar.paylibs.utils.LogUtil; import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
@ -14,19 +20,42 @@ import java.util.Calendar;
public class AutoAlarmReceiver extends BroadcastReceiver { public class AutoAlarmReceiver extends BroadcastReceiver {
private static final String TAG = AutoAlarmReceiver.class.getSimpleName(); private static final String TAG = AutoAlarmReceiver.class.getSimpleName();
private static final String WAKE_LOCK_TAG = "KBZAutoSettle::AlarmWakeLock";
private static final String NOTIFICATION_CHANNEL_ID = "AUTO_SETTLEMENT_ALARM";
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
LogUtil.d(TAG, "AutoAlarmReceiver triggered at: " + new java.util.Date().toString());
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
wakeLock.acquire(60000);
try {
showAlarmTriggeredNotification(context);
scheduleNextDayAlarm(context); scheduleNextDayAlarm(context);
try { try {
Intent serviceIntent = new Intent(context, AutoSettleService.class); Intent serviceIntent = new Intent(context, AutoSettleService.class);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent);
LogUtil.d(TAG, "AutoSettleService started as foreground service");
} else {
context.startService(serviceIntent); context.startService(serviceIntent);
LogUtil.d(TAG, "AutoSettleService started successfully"); LogUtil.d(TAG, "AutoSettleService started successfully");
}
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Failed to start AutoSettleService: " + e.getMessage()); LogUtil.e(TAG, "Failed to start AutoSettleService: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
} }
} finally {
// Release wake lock
if (wakeLock.isHeld()) {
wakeLock.release();
}
}
} }
private void scheduleNextDayAlarm(Context context) { private void scheduleNextDayAlarm(Context context) {
@ -78,7 +107,6 @@ public class AutoAlarmReceiver extends BroadcastReceiver {
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
); );
// Schedule next day's alarm
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
if (alarmManager.canScheduleExactAlarms()) { if (alarmManager.canScheduleExactAlarms()) {
@ -97,4 +125,32 @@ public class AutoAlarmReceiver extends BroadcastReceiver {
e.printStackTrace(); e.printStackTrace();
} }
} }
private void showAlarmTriggeredNotification(Context context) {
try {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"Auto Settlement Alarms",
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("Notifications for auto settlement alarm triggers");
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Auto Settlement Triggered")
.setContentText("Auto settlement alarm triggered at " + new java.util.Date().toString())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true);
notificationManager.notify(1001, builder.build());
} catch (Exception e) {
LogUtil.e(TAG, "Failed to show alarm notification: " + e.getMessage());
}
}
} }

View File

@ -3,8 +3,10 @@ package com.utsmm.kbz.service;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.text.TextUtils; import android.text.TextUtils;
@ -14,6 +16,11 @@ import androidx.core.app.NotificationCompat;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.google.gson.Gson;
import com.utsmm.kbz.MainActivity;
import com.utsmm.kbz.util.EReceiptUtil;
import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.repo.Repository; import com.utsmyanmar.baselib.repo.Repository;
import com.utsmm.kbz.BuildConfig; import com.utsmm.kbz.BuildConfig;
import com.utsmm.kbz.R; import com.utsmm.kbz.R;
@ -22,10 +29,34 @@ import com.utsmm.kbz.ui.settlement.SettlementViewModel;
import javax.inject.Inject; import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint; import dagger.hilt.android.AndroidEntryPoint;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers;
import retrofit2.HttpException;
import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.isobuilder.ISOMode;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX; import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion;
import com.utsmyanmar.paylibs.model.MsgField;
import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.SettleData;
import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.network.ISOCallback;
import com.utsmyanmar.paylibs.network.ISOSocket;
import com.utsmyanmar.paylibs.utils.LogUtil; import com.utsmyanmar.paylibs.utils.LogUtil;
import com.utsmyanmar.paylibs.utils.MessageType;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
import com.utsmyanmar.paylibs.utils.enums.HostName;
import com.utsmyanmar.paylibs.utils.iso_utils.BitmapConfig;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionType;
import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
import com.utsmyanmar.paylibs.utils.params.Params;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@AndroidEntryPoint @AndroidEntryPoint
public class AutoSettleService extends Service { public class AutoSettleService extends Service {
@ -49,9 +80,38 @@ public class AutoSettleService extends Service {
@Inject @Inject
Repository repository; Repository repository;
public static final String NOTIFICATION_CHANNEL_ID = "10001"; public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default"; private final static String default_notification_channel_id = "default";
private void startForegroundService() {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Create notification channel for Android 8+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"Auto Settlement Service",
NotificationManager.IMPORTANCE_LOW // Use LOW importance for foreground service
);
channel.setDescription("Auto settlement background service");
notificationManager.createNotificationChannel(channel);
}
// Create foreground notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Auto Settlement Active")
.setContentText("Processing scheduled settlement...")
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true) // Make it non-dismissible
.setAutoCancel(false);
// Start foreground service
startForeground(1002, builder.build());
}
private void createNotification() { private void createNotification() {
NotificationManager mNotificationManager = (NotificationManager)getSystemService( NOTIFICATION_SERVICE ) ; NotificationManager mNotificationManager = (NotificationManager)getSystemService( NOTIFICATION_SERVICE ) ;
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext() , default_notification_channel_id ) ; NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext() , default_notification_channel_id ) ;
@ -83,7 +143,14 @@ public class AutoSettleService extends Service {
LogUtil.d(TAG, "<<<<<<<<<<<<<<< Auto Settlement Service Started >>>>>>>>>>>>>>>>."); LogUtil.d(TAG, "<<<<<<<<<<<<<<< Auto Settlement Service Started >>>>>>>>>>>>>>>>.");
try { try {
// Start as foreground service for Android 8+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
startForegroundService();
}
sendDataToViewModel("Auto settlement initiated"); sendDataToViewModel("Auto settlement initiated");
// Also create regular notification
createNotification(); createNotification();
if (SystemParamsOperation.getInstance().getSettlementStatus()) { if (SystemParamsOperation.getInstance().getSettlementStatus()) {
@ -109,20 +176,19 @@ public class AutoSettleService extends Service {
} }
final ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder( final ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder(
com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion.VERSION_1993, ISOVersion.VERSION_1993,
com.utsmyanmar.paylibs.isobuilder.ISOMode.BOTH_HEADER_TPDU, ISOMode.BOTH_HEADER_TPDU,
com.utsmyanmar.paylibs.utils.enums.HostName.BPC HostName.BPC
).build(); ).build();
regularSettlementObserver = new Observer<java.util.List<com.utsmyanmar.paylibs.model.PayDetail>>() { regularSettlementObserver = new Observer<List<PayDetail>>() {
@Override @Override
public void onChanged(java.util.List<com.utsmyanmar.paylibs.model.PayDetail> list) { public void onChanged(List<PayDetail> list) {
if (regularSettlementCompleted) { if (regularSettlementCompleted) {
return; return;
} }
regularSettlementCompleted = true; regularSettlementCompleted = true;
// Remove observer immediately to prevent infinite loop
repository.getSettlementPOS().removeObserver(this); repository.getSettlementPOS().removeObserver(this);
int saleCount = 0; int saleCount = 0;
@ -135,33 +201,33 @@ public class AutoSettleService extends Service {
long caAmount = 0L; long caAmount = 0L;
if (list != null && !list.isEmpty()) { if (list != null && !list.isEmpty()) {
for (com.utsmyanmar.paylibs.model.PayDetail pay : list) { for (PayDetail pay : list) {
if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.SALE && !pay.isCanceled) { if (pay.getTransactionType() == TransactionType.SALE && !pay.isCanceled) {
saleCount++; saleCount++;
saleAmount += pay.getAmount(); saleAmount += pay.getAmount();
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.PRE_SALE_COMPLETE && !pay.isCanceled) { } else if (pay.getTransactionType() == TransactionType.PRE_SALE_COMPLETE && !pay.isCanceled) {
preCount++; preCount++;
preAmount += pay.getAmount(); preAmount += pay.getAmount();
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.REFUND) { } else if (pay.getTransactionType() == TransactionType.REFUND) {
refundCount++; refundCount++;
refundAmount += pay.getAmount(); refundAmount += pay.getAmount();
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.CASH_ADVANCE) { } else if (pay.getTransactionType() == TransactionType.CASH_ADVANCE) {
caCount++; caCount++;
caAmount += pay.getAmount(); caAmount += pay.getAmount();
} }
} }
} }
com.utsmyanmar.paylibs.model.TradeData tradeData = com.utsmyanmar.paylibs.utils.params.Params.newTrade(true); TradeData tradeData = Params.newTrade(true);
com.utsmyanmar.paylibs.model.PayDetail payDetail = tradeData.getPayDetail(); PayDetail payDetail = tradeData.getPayDetail();
String bitmap = com.utsmyanmar.paylibs.utils.iso_utils.BitmapConfig.BPC_SETTLEMENT; String bitmap = BitmapConfig.BPC_SETTLEMENT;
payDetail.setTransType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.name); payDetail.setTransType(TransactionsType.SETTLEMENT.name);
payDetail.setTransactionType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.SETTLEMENT); payDetail.setTransactionType(TransactionType.SETTLEMENT);
payDetail.setProcessCode(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.processCode); payDetail.setProcessCode(TransactionsType.SETTLEMENT.processCode);
payDetail.setBatchNo(com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation.getInstance().getCurrentBatchNum()); payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum());
com.utsmyanmar.paylibs.model.SettleData settleData = new com.utsmyanmar.paylibs.model.SettleData( SettleData settleData = new SettleData(
saleCount, saleAmount, preCount, preAmount, refundCount, refundAmount, caCount, caAmount); saleCount, saleAmount, preCount, preAmount, refundCount, refundAmount, caCount, caAmount);
payDetail.setSettleDataObj(settleData); payDetail.setSettleDataObj(settleData);
@ -171,24 +237,24 @@ public class AutoSettleService extends Service {
long creditTotal = saleAmount + preAmount + caAmount; long creditTotal = saleAmount + preAmount + caAmount;
long subTotal = creditTotal - refundAmount; long subTotal = creditTotal - refundAmount;
if (subTotal < 0L) { if (subTotal < 0L) {
settlementData = "D" + String.format(java.util.Locale.getDefault(), "%012d", Math.abs(subTotal)); settlementData = "D" + String.format(Locale.getDefault(), "%012d", Math.abs(subTotal));
} else { } else {
settlementData = "C" + String.format(java.util.Locale.getDefault(), "%012d", subTotal); settlementData = "C" + String.format(Locale.getDefault(), "%012d", subTotal);
} }
} else { } else {
settlementData = "C" + String.format(java.util.Locale.getDefault(), "%012d", totalAmount); settlementData = "C" + String.format(Locale.getDefault(), "%012d", totalAmount);
} }
payDetail.setSettleData(settlementData); payDetail.setSettleData(settlementData);
payDetail.setAmount(totalAmount); payDetail.setAmount(totalAmount);
tradeData.setPayDetail(payDetail); tradeData.setPayDetail(payDetail);
tradeData.setField60(com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation.getInstance().getCurrentBatchNum()); tradeData.setField60(SystemParamsOperation.getInstance().getCurrentBatchNum());
byte[] sendBytes = isoMsgX.buildISOPackets(tradeData, bitmap, com.utsmyanmar.paylibs.utils.MessageType.SETTLEMENT); byte[] sendBytes = isoMsgX.buildISOPackets(tradeData, bitmap, MessageType.SETTLEMENT);
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, new com.utsmyanmar.paylibs.network.ISOCallback() { ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, new ISOCallback() {
@Override @Override
public void onReceive(byte[] bytes, int length) { public void onReceive(byte[] bytes, int length) {
java.util.Map<String, com.utsmyanmar.paylibs.model.MsgField> responseMap = isoMsgX.parseISOPackets(bytes, length); Map<String, MsgField> responseMap = isoMsgX.parseISOPackets(bytes, length);
if (responseMap != null) { if (responseMap != null) {
String resultStr = ""; String resultStr = "";
try { try {
@ -199,7 +265,7 @@ public class AutoSettleService extends Service {
return; return;
} }
payDetail.setTradeAnswerCode(resultStr); payDetail.setTradeAnswerCode(resultStr);
if (TextUtils.equals(resultStr, com.utsmyanmar.paylibs.Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, com.utsmyanmar.paylibs.Constant.ANSWER_CODE_APPROVED)) { if (TextUtils.equals(resultStr, Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, Constant.ANSWER_CODE_APPROVED)) {
payDetail.setIsNeedReversal(false); payDetail.setIsNeedReversal(false);
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) { } else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
payDetail.setIsNeedReversal(true); payDetail.setIsNeedReversal(true);
@ -209,8 +275,8 @@ public class AutoSettleService extends Service {
@Override @Override
public void onError(String msg) { public void onError(String msg) {
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().switchIp(); ISOSocket.getInstance().switchIp();
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, this); ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, this);
} }
@Override @Override
@ -218,14 +284,14 @@ public class AutoSettleService extends Service {
LogUtil.d(TAG, "Auto settlement transaction completed successfully"); LogUtil.d(TAG, "Auto settlement transaction completed successfully");
if (list != null && !list.isEmpty()) { if (list != null && !list.isEmpty()) {
for (com.utsmyanmar.paylibs.model.PayDetail p : list) { for (PayDetail p : list) {
repository.deletePayDetail(p); repository.deletePayDetail(p);
} }
} }
repository.insertPayDetail(payDetail); repository.insertPayDetail(payDetail);
try { try {
com.utsmyanmar.paylibs.model.PayDetail cleanPayDetail = new com.utsmyanmar.paylibs.model.PayDetail(); PayDetail cleanPayDetail = new PayDetail();
cleanPayDetail.setTransType(payDetail.getTransType()); cleanPayDetail.setTransType(payDetail.getTransType());
cleanPayDetail.setTransactionType(payDetail.getTransactionType()); cleanPayDetail.setTransactionType(payDetail.getTransactionType());
cleanPayDetail.setProcessCode(payDetail.getProcessCode()); cleanPayDetail.setProcessCode(payDetail.getProcessCode());
@ -235,31 +301,12 @@ public class AutoSettleService extends Service {
cleanPayDetail.setTradeAnswerCode(payDetail.getTradeAnswerCode()); cleanPayDetail.setTradeAnswerCode(payDetail.getTradeAnswerCode());
cleanPayDetail.setIsNeedReversal(payDetail.getIsNeedReversal()); cleanPayDetail.setIsNeedReversal(payDetail.getIsNeedReversal());
Intent uiIntent = new Intent(getApplicationContext(), com.utsmm.kbz.MainActivity.class); // Use notification-based approach to reliably launch the app
uiIntent.putExtra("AUTO_SETTLEMENT", true); launchAppWithSettlementResult("AUTO_SETTLEMENT", cleanPayDetail, null);
uiIntent.putExtra("EXTRA_TRANSACTION_TYPE", com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.value);
uiIntent.putExtra("EXTRA_PAY_DETAIL", cleanPayDetail);
uiIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(uiIntent);
LogUtil.d(TAG, "MainActivity started successfully with auto settlement result");
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Error starting MainActivity: " + e.getMessage()); LogUtil.e(TAG, "Error launching app with settlement result: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
try {
Intent fallbackIntent = new Intent(getApplicationContext(), com.utsmm.kbz.MainActivity.class);
fallbackIntent.putExtra("AUTO_SETTLEMENT", true);
fallbackIntent.putExtra("EXTRA_TRANSACTION_TYPE", com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.value);
fallbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(fallbackIntent);
LogUtil.d(TAG, "MainActivity started with fallback approach");
} catch (Exception fallbackException) {
LogUtil.e(TAG, "Fallback also failed: " + fallbackException.getMessage());
}
} }
checkIfBothSettlementsComplete(); checkIfBothSettlementsComplete();
@ -276,15 +323,14 @@ public class AutoSettleService extends Service {
return; return;
} }
qrSettlementObserver = new Observer<java.util.List<com.utsmyanmar.paylibs.model.PayDetail>>() { qrSettlementObserver = new Observer<List<PayDetail>>() {
@Override @Override
public void onChanged(java.util.List<com.utsmyanmar.paylibs.model.PayDetail> payDetailList) { public void onChanged(List<PayDetail> payDetailList) {
if (qrSettlementCompleted) { if (qrSettlementCompleted) {
return; return;
} }
qrSettlementCompleted = true; qrSettlementCompleted = true;
// Remove observer immediately to prevent infinite loop
repository.getTransactionHistory().removeObserver(this); repository.getTransactionHistory().removeObserver(this);
if (payDetailList != null) { if (payDetailList != null) {
@ -293,28 +339,26 @@ public class AutoSettleService extends Service {
int qrRefundCount = 0; int qrRefundCount = 0;
long qrRefundAmount = 0; long qrRefundAmount = 0;
java.util.ArrayList<com.utsmyanmar.paylibs.model.PayDetail> qrTransactionsList = new java.util.ArrayList<>(); ArrayList<PayDetail> qrTransactionsList = new ArrayList<>();
java.util.ArrayList<com.utsmyanmar.paylibs.model.PayDetail> qrTransListAll = new java.util.ArrayList<>(); ArrayList<PayDetail> qrTransListAll = new ArrayList<>();
try { try {
for (com.utsmyanmar.paylibs.model.PayDetail payDetail : payDetailList) { for (PayDetail payDetail : payDetailList) {
// Filter for successful QR transactions only if ((payDetail.getTransactionType() == TransactionsType.MMQR.value
if ((payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR.value || payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value)
|| payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_REFUND.value)
&& payDetail.getQrTransStatus() == 1) { && payDetail.getQrTransStatus() == 1) {
qrTransactionsList.add(payDetail); qrTransactionsList.add(payDetail);
if (payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR.value) { if (payDetail.getTransactionType() == TransactionsType.MMQR.value) {
qrSaleCount++; qrSaleCount++;
qrSaleAmount += payDetail.getAmount(); qrSaleAmount += payDetail.getAmount();
} else if (payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_REFUND.value) { } else if (payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
qrRefundCount++; qrRefundCount++;
qrRefundAmount += payDetail.getAmount(); qrRefundAmount += payDetail.getAmount();
} }
} else if (payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR.value } else if (payDetail.getTransactionType() == TransactionsType.MMQR.value
|| payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_REFUND.value) { || payDetail.getTransactionType() == TransactionsType.MMQR_REFUND.value) {
// Include all QR transactions for deletion (successful and failed)
qrTransListAll.add(payDetail); qrTransListAll.add(payDetail);
} }
} }
@ -333,14 +377,14 @@ public class AutoSettleService extends Service {
SystemParamsOperation.getInstance().getIncrementBatchNo(); SystemParamsOperation.getInstance().getIncrementBatchNo();
// Create settlement data for QR transactions // Create settlement data for QR transactions
com.utsmyanmar.paylibs.model.SettleData settleData = new com.utsmyanmar.paylibs.model.SettleData( SettleData settleData = new SettleData(
qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L); qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
com.utsmyanmar.paylibs.model.TradeData tradeData = com.utsmyanmar.paylibs.utils.params.Params.newTrade(false); TradeData tradeData = Params.newTrade(false);
com.utsmyanmar.paylibs.model.PayDetail payDetail = tradeData.getPayDetail(); PayDetail payDetail = tradeData.getPayDetail();
payDetail.setSettleDataObj(settleData); payDetail.setSettleDataObj(settleData);
payDetail.setTransactionType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT.value); payDetail.setTransactionType(TransactionsType.MMQR_SETTLEMENT.value);
payDetail.setTransType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT.name); payDetail.setTransType(TransactionsType.MMQR_SETTLEMENT.name);
payDetail.setAmount(totalAmount); payDetail.setAmount(totalAmount);
payDetail.setTradeAnswerCode("000"); payDetail.setTradeAnswerCode("000");
payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum()); payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum());
@ -349,42 +393,38 @@ public class AutoSettleService extends Service {
repository.insertPayDetail(payDetail); repository.insertPayDetail(payDetail);
// Delete settled QR transactions // Delete settled QR transactions
for (com.utsmyanmar.paylibs.model.PayDetail pay : qrTransactionsList) { for (PayDetail pay : qrTransactionsList) {
repository.deletePayDetail(pay); repository.deletePayDetail(pay);
} }
// Delete all other QR transactions (failed ones) // Delete all other QR transactions (failed ones)
for (com.utsmyanmar.paylibs.model.PayDetail pay : qrTransListAll) { for (PayDetail pay : qrTransListAll) {
repository.deletePayDetail(pay); repository.deletePayDetail(pay);
} }
// Push e-receipt data // Push e-receipt data using repository directly
try { try {
com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest request = EReceiptRequest request = EReceiptUtil.getInstance().generateQRSettlement(payDetail);
com.utsmm.kbz.util.EReceiptUtil.getInstance().generateQRSettlement(payDetail); sendEReceipt(request);
LogUtil.d(TAG, "QR Settlement e-receipt data prepared"); LogUtil.d(TAG, "QR Settlement e-receipt data prepared and sent");
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Error preparing QR settlement e-receipt: " + e.getMessage()); LogUtil.e(TAG, "Error preparing QR settlement e-receipt: " + e.getMessage());
} }
try { try {
// Start MainActivity with QR settlement data for automatic printing // Create QR settlement data bundle
Intent uiIntent = new Intent(getApplicationContext(), com.utsmm.kbz.MainActivity.class); Bundle qrData = new Bundle();
uiIntent.putExtra("AUTO_QR_SETTLEMENT", true); qrData.putInt("QR_SALE_COUNT", qrSaleCount);
uiIntent.putExtra("EXTRA_TRANSACTION_TYPE", com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT.value); qrData.putLong("QR_SALE_AMOUNT", qrSaleAmount);
uiIntent.putExtra("QR_SALE_COUNT", qrSaleCount); qrData.putInt("QR_REFUND_COUNT", qrRefundCount);
uiIntent.putExtra("QR_SALE_AMOUNT", qrSaleAmount); qrData.putLong("QR_REFUND_AMOUNT", qrRefundAmount);
uiIntent.putExtra("QR_REFUND_COUNT", qrRefundCount); qrData.putLong("QR_TOTAL_AMOUNT", totalAmount);
uiIntent.putExtra("QR_REFUND_AMOUNT", qrRefundAmount); qrData.putSerializable("QR_TRANS_LIST", qrTransactionsList);
uiIntent.putExtra("QR_TOTAL_AMOUNT", totalAmount); // Use notification-based approach to reliably launch the app
uiIntent.putExtra("QR_TRANS_LIST", qrTransactionsList); launchAppWithSettlementResult("AUTO_QR_SETTLEMENT", null, qrData);
uiIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(uiIntent);
LogUtil.d(TAG, "MainActivity started successfully with QR auto settlement result");
} catch (Exception e) { } catch (Exception e) {
LogUtil.e(TAG, "Error starting MainActivity for QR settlement: " + e.getMessage()); LogUtil.e(TAG, "Error launching app for QR settlement: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
} }
@ -402,7 +442,6 @@ public class AutoSettleService extends Service {
} }
private void checkIfBothSettlementsComplete() { private void checkIfBothSettlementsComplete() {
// Stop service only when both settlements are processed (or skipped if no data)
if (regularSettlementCompleted && qrSettlementCompleted) { if (regularSettlementCompleted && qrSettlementCompleted) {
LogUtil.d(TAG, "Both settlements completed, stopping service"); LogUtil.d(TAG, "Both settlements completed, stopping service");
stopSelf(); stopSelf();
@ -438,6 +477,96 @@ public class AutoSettleService extends Service {
repository.getTransactionHistory().removeObserver(qrSettlementObserver); repository.getTransactionHistory().removeObserver(qrSettlementObserver);
} }
LogUtil.d(TAG, "AutoSettleService destroyed and cleaned up"); }
private void launchAppWithSettlementResult(String settlementType,
PayDetail payDetail,
Bundle qrData) {
try {
Intent launchIntent = new Intent(this, MainActivity.class);
launchIntent.putExtra(settlementType, true);
if ("AUTO_SETTLEMENT".equals(settlementType) && payDetail != null) {
launchIntent.putExtra("EXTRA_TRANSACTION_TYPE", TransactionsType.SETTLEMENT.value);
launchIntent.putExtra("EXTRA_PAY_DETAIL", payDetail);
} else if ("AUTO_QR_SETTLEMENT".equals(settlementType) && qrData != null) {
launchIntent.putExtra("EXTRA_TRANSACTION_TYPE", TransactionsType.MMQR_SETTLEMENT.value);
launchIntent.putExtras(qrData);
}
PendingIntent pendingIntent = PendingIntent.getActivity(
this,
(int) System.currentTimeMillis(),
launchIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"SETTLEMENT_COMPLETE",
"Settlement Complete",
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("Auto settlement completion notifications");
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "SETTLEMENT_COMPLETE")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Auto Settlement Complete")
.setContentText("Tap to view settlement results and print receipt")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setFullScreenIntent(pendingIntent, true);
notificationManager.notify(2001, builder.build());
LogUtil.d(TAG, " Settlement complete notification created - will launch app when tapped");
try {
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP |
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(launchIntent);
} catch (Exception directException) {
LogUtil.d(TAG, "Direct launch failed (expected on modern Android), notification approach will handle it");
}
} catch (Exception e) {
LogUtil.e(TAG, "Error creating settlement notification: " + e.getMessage());
e.printStackTrace();
}
}
private void sendEReceipt(EReceiptRequest request) {
try {
LogUtil.d(TAG, "Sending e-receipt: " + new Gson().toJson(request));
repository.sendReceipt(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> LogUtil.d(TAG, "E-Receipt sent successfully: " + response.getMessage()),
error -> {
if (error instanceof HttpException) {
HttpException httpEx = (HttpException) error;
try {
String errorJson = httpEx.response().errorBody().string();
LogUtil.e(TAG, "E-Receipt error: " + errorJson);
} catch (Exception e) {
LogUtil.e(TAG, "E-Receipt send failed: " + error.getMessage());
}
} else {
LogUtil.e(TAG, "E-Receipt send failed: " + error.getMessage());
}
}
);
} catch (Exception e) {
LogUtil.e(TAG, "Error sending e-receipt: " + e.getMessage());
}
} }
} }

View File

@ -27,6 +27,7 @@ import com.utsmyanmar.paylibs.Constant;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.print.PaperRollStatusCallback; import com.utsmyanmar.paylibs.print.PaperRollStatusCallback;
import com.utsmyanmar.paylibs.print.PrintHelper; import com.utsmyanmar.paylibs.print.PrintHelper;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
import com.utsmyanmar.paylibs.utils.PrintStatus; import com.utsmyanmar.paylibs.utils.PrintStatus;
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;
@ -210,7 +211,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
startPrintProcess(true); startPrintProcess(true);
downloadParameters(siriusReq, TMSUpdate.UPDATE); downloadParameters(siriusReq, TMSUpdate.UPDATE);
// showSuccessDialog(getResourceString(R.string.txt_configs_are_updated)); // showSuccessDialog(getResourceString(R.string.txt_configs_are_updated));
navigateToMainScreen(); // navigateToMainScreen();
} }
private void handleQRPaySuccessTransaction(PayDetail payDetail, SiriusRequest siriusReq) { private void handleQRPaySuccessTransaction(PayDetail payDetail, SiriusRequest siriusReq) {
@ -320,7 +321,17 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
@Override @Override
public void printerReady() { public void printerReady() {
if(isSettlement) { if(isSettlement) {
sharedViewModel.startPrintSettlement(); sharedViewModel.startPrintSettlement(new PrintXStatus() {
@Override
public void onSuccess() {
isCardInside();
}
@Override
public void onFailure() {
handleForEmptyPaperRoll(isSettlement);
}
});
return; return;
} }
sharedViewModel.startPrintProcess(); sharedViewModel.startPrintProcess();
@ -328,26 +339,7 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
@Override @Override
public void paperRollIsEmpty() { public void paperRollIsEmpty() {
cancelTimeout(); handleForEmptyPaperRoll(isSettlement);
showPrinterAlertDialog(getResourceString(R.string.txt_paper_roll_not_ready), new DialogCallback() {
@Override
public void onClickCancel() {
dismissPrinterAlertDialog();
isCardInside();
}
@Override
public void onClickRetry() {
dismissPrinterAlertDialog();
startPrintProcess(isSettlement);
}
});
if(SystemParamsOperation.getInstance().isAlertSound()) {
startSound(getResourceString(R.string.txt_audio_printer_alert));
}
} }
@Override @Override
@ -374,6 +366,30 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
}); });
} }
private void handleForEmptyPaperRoll(boolean isSettle) {
cancelTimeout();
showPrinterAlertDialog(getResourceString(R.string.txt_paper_roll_not_ready), new DialogCallback() {
@Override
public void onClickCancel() {
dismissPrinterAlertDialog();
isCardInside();
}
@Override
public void onClickRetry() {
dismissPrinterAlertDialog();
startPrintProcess(isSettle);
}
});
if(SystemParamsOperation.getInstance().isAlertSound()) {
startSound(getResourceString(R.string.txt_audio_printer_alert));
}
}
private void alertPaperRoll(String title, String message) { private void alertPaperRoll(String title, String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
builder.setTitle(title) builder.setTitle(title)

View File

@ -396,49 +396,29 @@ public class SharedViewModel extends ViewModel {
} }
public void startPrintSettlement() { public void startPrintSettlement(PrintXStatus printXStatus) {
if(payDetail.getValue() == null) return; if(payDetail.getValue() == null) return;
if(payDetail.getValue().getTransactionType() == TransactionsType.SETTLEMENT.value) { if(payDetail.getValue().getTransactionType() == TransactionsType.SETTLEMENT.value) {
startPrintProcessSettlement(); startPrintProcessSettlement(printXStatus);
} else { } else {
startPrintProcessQRSettlement(); startPrintProcessQRSettlement(printXStatus);
} }
} }
public void startPrintProcessSettlement() { public void startPrintProcessSettlement(PrintXStatus printXStatus) {
if(payDetail.getValue() == null) return; if(payDetail.getValue() == null) return;
PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(), new PrintXStatus() { PrintXReceipt.getInstance().printSmileSettlementReport(payDetail.getValue(),printXStatus);
@Override
public void onSuccess() {
} }
@Override private void startPrintProcessQRSettlement(PrintXStatus printXStatus) {
public void onFailure() {
}
});
}
private void startPrintProcessQRSettlement() {
if(payDetail.getValue() == null && payDetails.getValue() == null) return; if(payDetail.getValue() == null && payDetails.getValue() == null) return;
PrintXReceipt.getInstance().printQRSettlementReport(payDetail.getValue(),payDetails.getValue(), new PrintXStatus() { PrintXReceipt.getInstance().printQRSettlementReport(payDetail.getValue(),payDetails.getValue(), printXStatus);
@Override
public void onSuccess() {
}
@Override
public void onFailure() {
}
});
} }

View File

@ -14,6 +14,7 @@ import com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest;
import com.utsmyanmar.baselib.util.DataBindingConfig; import com.utsmyanmar.baselib.util.DataBindingConfig;
import com.utsmyanmar.paylibs.model.PayDetail; import com.utsmyanmar.paylibs.model.PayDetail;
import com.utsmyanmar.paylibs.model.TradeData; import com.utsmyanmar.paylibs.model.TradeData;
import com.utsmyanmar.paylibs.print.printx.PrintXStatus;
import com.utsmyanmar.paylibs.sign_on.EchoTestProcess; import com.utsmyanmar.paylibs.sign_on.EchoTestProcess;
import com.utsmyanmar.paylibs.sign_on.SignOnListener; import com.utsmyanmar.paylibs.sign_on.SignOnListener;
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
@ -391,7 +392,17 @@ public class SettlementTransactionFragment extends DataBindingFragment implement
settlementViewModel.startSettlementProcess(); settlementViewModel.startSettlementProcess();
showLoadingDialog("Sending ..."); showLoadingDialog("Sending ...");
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH) { } else if(sharedViewModel.getTransMenu().getValue() == TransMenu.REVIEW_BATCH) {
sharedViewModel.startPrintSettlement(); sharedViewModel.startPrintSettlement(new PrintXStatus() {
@Override
public void onSuccess() {
}
@Override
public void onFailure() {
}
});
} else if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT) { } else if(sharedViewModel.getTransMenu().getValue() == TransMenu.LAST_SETTLEMENT) {
routeId = R.id.action_settlementTransactionFragment_to_reprintReceiptFragment; routeId = R.id.action_settlementTransactionFragment_to_reprintReceiptFragment;
safeNavigateToRouteId(); safeNavigateToRouteId();

View File

@ -4,6 +4,9 @@ import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.PowerManager;
import android.provider.Settings;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
@ -220,6 +223,10 @@ public class TMSProcessFragment extends DataBindingFragment {
CurrencyType currencyType = SystemParamsOperation.getInstance().getCurrencyType(); CurrencyType currencyType = SystemParamsOperation.getInstance().getCurrencyType();
sharedViewModel.set_currencyText(currencyType.name); sharedViewModel.set_currencyText(currencyType.name);
// tmsProcessViewModel.loadEmvParameters(); // tmsProcessViewModel.loadEmvParameters();
// Check and request battery optimization exemption before scheduling alarm
requestBatteryOptimizationExemption();
scheduleAutoSettlement(); scheduleAutoSettlement();
navigateToMain(); navigateToMain();
} }
@ -327,4 +334,40 @@ public class TMSProcessFragment extends DataBindingFragment {
} }
} }
private void requestBatteryOptimizationExemption() {
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
PowerManager powerManager = (PowerManager) requireContext().getSystemService(Context.POWER_SERVICE);
String packageName = requireContext().getPackageName();
if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
LogUtil.d(TAG, "Requesting battery optimization exemption for reliable alarms");
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
try {
startActivity(intent);
LogUtil.d(TAG, "Battery optimization exemption dialog opened");
} catch (Exception e) {
LogUtil.e(TAG, "Failed to open battery optimization dialog: " + e.getMessage());
// Fallback: Open battery optimization settings page
try {
Intent fallbackIntent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
startActivity(fallbackIntent);
LogUtil.d(TAG, "Battery optimization settings opened as fallback");
} catch (Exception fallbackException) {
LogUtil.e(TAG, "Fallback also failed: " + fallbackException.getMessage());
}
}
} else {
LogUtil.d(TAG, "App is already exempted from battery optimizations");
}
}
} catch (Exception e) {
LogUtil.e(TAG, "Error checking battery optimization status: " + e.getMessage());
}
}
} }

View File

@ -36,6 +36,7 @@ public class EReceiptUtil {
private String packageName; private String packageName;
private String qrTerminalId; private String qrTerminalId;
private String qrMerchantId; private String qrMerchantId;
private EReceiptUtil() { private EReceiptUtil() {
terminalId = SystemParamsOperation.getInstance().getTerminalId(); terminalId = SystemParamsOperation.getInstance().getTerminalId();
merchantId = SystemParamsOperation.getInstance().getMerchantId(); merchantId = SystemParamsOperation.getInstance().getMerchantId();
@ -95,8 +96,6 @@ public class EReceiptUtil {
} }
return request; return request;
} }
@ -154,8 +153,6 @@ public class EReceiptUtil {
} }
return request; return request;
} }
@ -248,10 +245,9 @@ public class EReceiptUtil {
request.setTerminalId(terminalId);//terminalId is not tid request.setTerminalId(terminalId);//terminalId is not tid
request.setShortCode(qrMerchantId); request.setShortCode(qrMerchantId);
if(payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value) {
SettleData settleData = payDetail.getSettleDataObj(); SettleData settleData = payDetail.getSettleDataObj();
long totalAmt = settleData.getSaleAmount() + settleData.getRefundAmount() + settleData.getPreAuthCompAmount() + settleData.getCashAdvanceAmount(); long totalAmt = settleData.getSaleAmount() + settleData.getRefundAmount();
double realTotalAmount = totalAmt / 100.0; double realTotalAmount = totalAmt / 100.0;
String totalAmount = df.format(realTotalAmount); String totalAmount = df.format(realTotalAmount);
request.setDE4(totalAmount); request.setDE4(totalAmount);
@ -261,10 +257,7 @@ public class EReceiptUtil {
request.setDE63_02(settleData.getSaleAmount() + ""); request.setDE63_02(settleData.getSaleAmount() + "");
request.setDE63_03(settleData.getRefundCount() + ""); request.setDE63_03(settleData.getRefundCount() + "");
request.setDE63_04(settleData.getRefundAmount() + ""); request.setDE63_04(settleData.getRefundAmount() + "");
request.setDE63_05(settleData.getPreAuthCompCount()+"");
request.setDE63_06(settleData.getPreAuthCompAmount()+"");
request.setDE63_07(settleData.getCashAdvanceCount()+"");
request.setDE63_08(settleData.getCashAdvanceAmount()+"");
invoiceNo = SystemParamsOperation.getInstance().getIncrementInvoiceNum(); invoiceNo = SystemParamsOperation.getInstance().getIncrementInvoiceNum();
request.setBatchNumber(batchNumber); request.setBatchNumber(batchNumber);
request.setInvoiceNumber(invoiceNo); request.setInvoiceNumber(invoiceNo);
@ -272,28 +265,7 @@ public class EReceiptUtil {
request.setDE39("A"); request.setDE39("A");
request.setDE37("0000"); request.setDE37("0000");
request.setDE49("MMK"); request.setDE49("MMK");
} else {
request.setDE2(POSUtil.getInstance().getCardNumMasking(payDetail.getCardNo()));
request.setDE4(amount);
request.setDE37(payDetail.getReferNo());
request.setDE38(payDetail.getApprovalCode());
// will check it later for currency code
request.setDE49("MMK");
request.setInvoiceNumber(payDetail.getInvoiceNo());
request.setCardLabel("MPU");
if(payDetail.getTradeAnswerCode().equals("000") || payDetail.getTradeAnswerCode().equals("00") ) {
request.setDescription("success");
request.setDE39("A");
} else {
request.setDescription(BaseErrorCode.getErrorMessage(payDetail.getTradeAnswerCode()));
request.setDE39("E");
}
}
request.setDE41(terminalId); request.setDE41(terminalId);
request.setDE42(merchantId); request.setDE42(merchantId);