QR Auto Settlement draft version,still need to optimize it
This commit is contained in:
parent
6c596cb061
commit
bcbe16e201
@ -34,6 +34,7 @@ import com.utsmyanmar.baselib.ui.AnimationDialog;
|
|||||||
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
|
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
|
||||||
import com.utsmyanmar.ecr.ECRHelper;
|
import com.utsmyanmar.ecr.ECRHelper;
|
||||||
import com.utsmyanmar.paylibs.Constant;
|
import com.utsmyanmar.paylibs.Constant;
|
||||||
|
import com.utsmyanmar.paylibs.model.PayDetail;
|
||||||
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
|
import com.utsmyanmar.paylibs.print.printx.PrintXReceipt;
|
||||||
import com.utsmyanmar.paylibs.utils.POSUtil;
|
import com.utsmyanmar.paylibs.utils.POSUtil;
|
||||||
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
|
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
|
||||||
@ -51,6 +52,7 @@ import com.utsmm.kbz.util.tms.TMSUtil;
|
|||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -408,17 +410,55 @@ public class MainActivity extends AppCompatActivity implements
|
|||||||
|
|
||||||
private void handleAutoSettlementIntent(Intent intent) {
|
private void handleAutoSettlementIntent(Intent intent) {
|
||||||
if (intent == null) return;
|
if (intent == null) return;
|
||||||
boolean auto = intent.getBooleanExtra("AUTO_SETTLEMENT", false);
|
|
||||||
if (!auto) return;
|
|
||||||
|
|
||||||
com.utsmyanmar.paylibs.model.PayDetail payDetail = (com.utsmyanmar.paylibs.model.PayDetail) intent.getSerializableExtra("EXTRA_PAY_DETAIL");
|
// Handle regular auto settlement
|
||||||
if (payDetail != null) {
|
boolean auto = intent.getBooleanExtra("AUTO_SETTLEMENT", false);
|
||||||
|
if (auto) {
|
||||||
|
com.utsmyanmar.paylibs.model.PayDetail payDetail = (com.utsmyanmar.paylibs.model.PayDetail) intent.getSerializableExtra("EXTRA_PAY_DETAIL");
|
||||||
|
if (payDetail != null) {
|
||||||
|
sharedViewModel.payDetail.setValue(payDetail);
|
||||||
|
sharedViewModel.transactionsType.setValue(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT);
|
||||||
|
try {
|
||||||
|
navController.navigate(R.id.transactionResultFragment);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.e(TAG, "Navigation error: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle QR auto settlement
|
||||||
|
boolean autoQR = intent.getBooleanExtra("AUTO_QR_SETTLEMENT", false);
|
||||||
|
if (autoQR) {
|
||||||
|
int qrSaleCount = intent.getIntExtra("QR_SALE_COUNT", 0);
|
||||||
|
long qrSaleAmount = intent.getLongExtra("QR_SALE_AMOUNT", 0L);
|
||||||
|
int qrRefundCount = intent.getIntExtra("QR_REFUND_COUNT", 0);
|
||||||
|
long qrRefundAmount = intent.getLongExtra("QR_REFUND_AMOUNT", 0L);
|
||||||
|
long totalAmount = intent.getLongExtra("QR_TOTAL_AMOUNT", 0L);
|
||||||
|
List<PayDetail> qrTransList = (List<PayDetail>) intent.getSerializableExtra("QR_TRANS_LIST");
|
||||||
|
|
||||||
|
// Create QR settlement PayDetail
|
||||||
|
com.utsmyanmar.paylibs.model.SettleData settleData = new com.utsmyanmar.paylibs.model.SettleData(
|
||||||
|
qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
|
||||||
|
|
||||||
|
com.utsmyanmar.paylibs.model.TradeData tradeData = com.utsmyanmar.paylibs.utils.params.Params.newTrade(false);
|
||||||
|
com.utsmyanmar.paylibs.model.PayDetail payDetail = tradeData.getPayDetail();
|
||||||
|
payDetail.setSettleDataObj(settleData);
|
||||||
|
payDetail.setTransactionType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT.value);
|
||||||
|
payDetail.setTransType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT.name);
|
||||||
|
payDetail.setAmount(totalAmount);
|
||||||
|
payDetail.setTradeAnswerCode("000");
|
||||||
|
|
||||||
|
// Note: QR transactions list is not passed to avoid serialization issues
|
||||||
|
// The settlement summary is sufficient for the receipt
|
||||||
|
sharedViewModel.payDetails.setValue(qrTransList);
|
||||||
sharedViewModel.payDetail.setValue(payDetail);
|
sharedViewModel.payDetail.setValue(payDetail);
|
||||||
sharedViewModel.transactionsType.setValue(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT);
|
sharedViewModel.transactionsType.setValue(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
navController.navigate(R.id.transactionResultFragment);
|
navController.navigate(R.id.transactionResultFragment);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.e(TAG, "Navigation error: " + e.getMessage());
|
LogUtil.e(TAG, "QR Auto Settlement navigation error: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -147,7 +147,7 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
delayFunctionCall(()-> {
|
delayFunctionCall(()-> {
|
||||||
NexGoSDK.getInstance().cancelCheckCard();
|
NexGoSDK.getInstance().cancelCheckCard();
|
||||||
NexGoSDK.getInstance().closeReader();
|
NexGoSDK.getInstance().closeReader();
|
||||||
disableHomeButton();
|
enableHomeButton();
|
||||||
disableTaskButton();
|
disableTaskButton();
|
||||||
BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
|
BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
|
||||||
});
|
});
|
||||||
@ -196,14 +196,8 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void checkDownload() {
|
private void checkDownload() {
|
||||||
Log.d(TAG, "Calling from Check download: ");
|
Log.d(TAG, "Calling from Check download: ");
|
||||||
if (!SystemParamsOperation.getInstance().isDownloadedParams() && SystemParamsOperation.getInstance().isActive() && tmsProcessViewModel.getIsCalled().getValue() == null) {
|
if (!SystemParamsOperation.getInstance().isDownloadedParams() && SystemParamsOperation.getInstance().isActive() && tmsProcessViewModel.getIsCalled().getValue() == null) {
|
||||||
@ -243,7 +237,7 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus());
|
sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus());
|
||||||
|
|
||||||
|
|
||||||
// generateMockQR();
|
generateMockQR();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -830,15 +824,15 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void generateMockQR() {
|
private void generateMockQR() {
|
||||||
// String transDate = "23/12/25";
|
String transDate = "24/12/25";
|
||||||
// String transTime = "12:06:30";
|
String transTime = "12:06:30";
|
||||||
// TradeData tradeData = MockData.getInstance().generateMockDataWithTime(TransactionsType.MMQR, 1,transDate,transTime);
|
TradeData tradeData = MockData.getInstance().generateMockDataWithTime(TransactionsType.MMQR, 1,transDate,transTime);
|
||||||
// PayDetail payDetail = tradeData.getPayDetail();
|
PayDetail payDetail = tradeData.getPayDetail();
|
||||||
// sharedViewModel.insertPayDetail(payDetail);
|
sharedViewModel.insertPayDetail(payDetail);
|
||||||
// LogUtil.d(TAG,"------------------- Inserted Mocked Data ------------------");
|
LogUtil.d(TAG,"------------------- Inserted Mocked Data ------------------");
|
||||||
// LogUtil.d(TAG,"trans date : "+payDetail.getTransDate() +"- Trans Time: "+payDetail.getTransTime());
|
LogUtil.d(TAG,"trans date : "+payDetail.getTransDate() +"- Trans Time: "+payDetail.getTransTime());
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
|
||||||
public class ClickEvent {
|
public class ClickEvent {
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
package com.utsmm.kbz.service;
|
package com.utsmm.kbz.service;
|
||||||
|
|
||||||
|
import android.app.AlarmManager;
|
||||||
|
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 com.utsmyanmar.paylibs.utils.LogUtil;
|
import com.utsmyanmar.paylibs.utils.LogUtil;
|
||||||
|
import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
public class AutoAlarmReceiver extends BroadcastReceiver {
|
public class AutoAlarmReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@ -12,17 +17,84 @@ public class AutoAlarmReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
@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());
|
|
||||||
|
|
||||||
boolean isTestAlarm = intent.getBooleanExtra("TEST_ALARM", false);
|
scheduleNextDayAlarm(context);
|
||||||
if (isTestAlarm) {
|
try {
|
||||||
LogUtil.d(TAG, "This is a test alarm - AutoAlarmReceiver is working correctly!");
|
Intent serviceIntent = new Intent(context, AutoSettleService.class);
|
||||||
|
context.startService(serviceIntent);
|
||||||
|
LogUtil.d(TAG, "AutoSettleService started successfully");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.e(TAG, "Failed to start AutoSettleService: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start the service to send the API request
|
private void scheduleNextDayAlarm(Context context) {
|
||||||
Intent serviceIntent = new Intent(context, AutoSettleService.class);
|
try {
|
||||||
context.startService(serviceIntent);
|
String timeStr = SystemParamsOperation.getInstance().getClearBatchTime();
|
||||||
|
LogUtil.d(TAG, " Rescheduling next day's alarm for timeStr: " + timeStr);
|
||||||
|
|
||||||
LogUtil.d(TAG, "AutoSettleService started");
|
if (timeStr == null || timeStr.trim().isEmpty()) {
|
||||||
|
LogUtil.d(TAG, "Clear batch time is empty, cannot reschedule");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = timeStr.trim().split(":");
|
||||||
|
if (parts.length != 2) {
|
||||||
|
LogUtil.d(TAG, "Invalid time format: " + timeStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hour = Integer.parseInt(parts[0]);
|
||||||
|
int minute = Integer.parseInt(parts[1]);
|
||||||
|
|
||||||
|
// Validate time range
|
||||||
|
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
|
||||||
|
LogUtil.d(TAG, "Invalid time values - hour: " + hour + ", minute: " + minute);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up next day's alarm
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.add(Calendar.DAY_OF_YEAR, 1); // Next day
|
||||||
|
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
||||||
|
calendar.set(Calendar.MINUTE, minute);
|
||||||
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
calendar.set(Calendar.MILLISECOND, 0);
|
||||||
|
|
||||||
|
long nextTriggerTime = calendar.getTimeInMillis();
|
||||||
|
|
||||||
|
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||||
|
if (alarmManager == null) {
|
||||||
|
LogUtil.e(TAG, "AlarmManager is null, cannot reschedule");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Intent intent = new Intent(context, AutoAlarmReceiver.class);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
1001,
|
||||||
|
intent,
|
||||||
|
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.S) {
|
||||||
|
if (alarmManager.canScheduleExactAlarms()) {
|
||||||
|
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextTriggerTime, pendingIntent);
|
||||||
|
} else {
|
||||||
|
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextTriggerTime, pendingIntent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextTriggerTime, pendingIntent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextTriggerTime, pendingIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import android.text.TextUtils;
|
|||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
import com.utsmyanmar.baselib.repo.Repository;
|
import com.utsmyanmar.baselib.repo.Repository;
|
||||||
@ -20,7 +21,6 @@ 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 com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
|
import com.utsmyanmar.paylibs.isobuilder.builderx.ISOMsgX;
|
||||||
@ -35,28 +35,34 @@ public class AutoSettleService extends Service {
|
|||||||
public static final String ACTION_DATA_RECEIVED = BuildConfig.APPLICATION_ID + ".ACTION_DATA_RECEIVED";
|
public static final String ACTION_DATA_RECEIVED = BuildConfig.APPLICATION_ID + ".ACTION_DATA_RECEIVED";
|
||||||
public static final String EXTRA_DATA = BuildConfig.APPLICATION_ID + ".EXTRA_DATA";
|
public static final String EXTRA_DATA = BuildConfig.APPLICATION_ID + ".EXTRA_DATA";
|
||||||
|
|
||||||
|
|
||||||
private Handler handler;
|
private Handler handler;
|
||||||
|
|
||||||
|
|
||||||
private SettlementViewModel settlementViewModel;
|
private SettlementViewModel settlementViewModel;
|
||||||
|
|
||||||
|
// Flags to prevent infinite loops
|
||||||
|
private boolean regularSettlementCompleted = false;
|
||||||
|
private boolean qrSettlementCompleted = false;
|
||||||
|
|
||||||
|
// Observers to keep reference for cleanup
|
||||||
|
private Observer<java.util.List<com.utsmyanmar.paylibs.model.PayDetail>> regularSettlementObserver;
|
||||||
|
private Observer<java.util.List<com.utsmyanmar.paylibs.model.PayDetail>> qrSettlementObserver;
|
||||||
|
|
||||||
@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 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 ) ;
|
||||||
mBuilder.setContentTitle( "Alarm manager is running!" ) ;
|
mBuilder.setContentTitle( "Auto Settlement Running" ) ;
|
||||||
mBuilder.setContentText( "Wiping out the transactions!" ) ;
|
mBuilder.setContentText( "Processing transactions..." ) ;
|
||||||
mBuilder.setTicker( "Notification Listener Service Example" ) ;
|
mBuilder.setTicker( "Auto Settlement Service" ) ;
|
||||||
mBuilder.setSmallIcon(R.drawable. ic_launcher_foreground ) ;
|
mBuilder.setSmallIcon(R.drawable. ic_launcher_foreground ) ;
|
||||||
mBuilder.setAutoCancel( true ) ;
|
mBuilder.setAutoCancel( true ) ;
|
||||||
if (android.os.Build.VERSION. SDK_INT >= android.os.Build.VERSION_CODES. O ) {
|
if (android.os.Build.VERSION. SDK_INT >= android.os.Build.VERSION_CODES. O ) {
|
||||||
int importance = NotificationManager. IMPORTANCE_HIGH ;
|
int importance = NotificationManager. IMPORTANCE_HIGH ;
|
||||||
NotificationChannel notificationChannel = new NotificationChannel( NOTIFICATION_CHANNEL_ID , "NOTIFICATION_CHANNEL_NAME" , importance) ;
|
NotificationChannel notificationChannel = new NotificationChannel( NOTIFICATION_CHANNEL_ID , "AUTO_SETTLEMENT_CHANNEL" , importance) ;
|
||||||
mBuilder.setChannelId( NOTIFICATION_CHANNEL_ID ) ;
|
mBuilder.setChannelId( NOTIFICATION_CHANNEL_ID ) ;
|
||||||
assert mNotificationManager != null;
|
assert mNotificationManager != null;
|
||||||
mNotificationManager.createNotificationChannel(notificationChannel) ;
|
mNotificationManager.createNotificationChannel(notificationChannel) ;
|
||||||
@ -74,15 +80,16 @@ public class AutoSettleService extends Service {
|
|||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
// Perform the Settlement request here
|
|
||||||
LogUtil.d(TAG, "<<<<<<<<<<<<<<< Auto Settlement Service Started >>>>>>>>>>>>>>>>.");
|
LogUtil.d(TAG, "<<<<<<<<<<<<<<< Auto Settlement Service Started >>>>>>>>>>>>>>>>.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sendDataToViewModel("Hello there");
|
sendDataToViewModel("Auto settlement initiated");
|
||||||
createNotification();
|
createNotification();
|
||||||
|
|
||||||
if (SystemParamsOperation.getInstance().getSettlementStatus()) {
|
if (SystemParamsOperation.getInstance().getSettlementStatus()) {
|
||||||
performSettlement();
|
// performSettlement();
|
||||||
|
regularSettlementCompleted = true;
|
||||||
|
performQRSettlement();
|
||||||
} else {
|
} else {
|
||||||
LogUtil.d(TAG, "Settlement is disabled in system parameters");
|
LogUtil.d(TAG, "Settlement is disabled in system parameters");
|
||||||
stopSelf();
|
stopSelf();
|
||||||
@ -97,175 +104,315 @@ public class AutoSettleService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void performSettlement() {
|
private void performSettlement() {
|
||||||
|
if (regularSettlementCompleted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder(
|
final ISOMsgX isoMsgX = new ISOMsgX.ISOMsgXBuilder(
|
||||||
com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion.VERSION_1993,
|
com.utsmyanmar.paylibs.isobuilder.builderx.ISOVersion.VERSION_1993,
|
||||||
com.utsmyanmar.paylibs.isobuilder.ISOMode.BOTH_HEADER_TPDU,
|
com.utsmyanmar.paylibs.isobuilder.ISOMode.BOTH_HEADER_TPDU,
|
||||||
com.utsmyanmar.paylibs.utils.enums.HostName.BPC
|
com.utsmyanmar.paylibs.utils.enums.HostName.BPC
|
||||||
).build();
|
).build();
|
||||||
|
|
||||||
repository.getSettlementPOS().observeForever(list -> {
|
regularSettlementObserver = new Observer<java.util.List<com.utsmyanmar.paylibs.model.PayDetail>>() {
|
||||||
int saleCount = 0;
|
@Override
|
||||||
long saleAmount = 0L;
|
public void onChanged(java.util.List<com.utsmyanmar.paylibs.model.PayDetail> list) {
|
||||||
int preCount = 0;
|
if (regularSettlementCompleted) {
|
||||||
long preAmount = 0L;
|
return;
|
||||||
int refundCount = 0;
|
}
|
||||||
long refundAmount = 0L;
|
regularSettlementCompleted = true;
|
||||||
int caCount = 0;
|
|
||||||
long caAmount = 0L;
|
|
||||||
|
|
||||||
if (list != null && !list.isEmpty()) {
|
// Remove observer immediately to prevent infinite loop
|
||||||
for (com.utsmyanmar.paylibs.model.PayDetail pay : list) {
|
repository.getSettlementPOS().removeObserver(this);
|
||||||
if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.SALE && !pay.isCanceled) {
|
|
||||||
saleCount++;
|
int saleCount = 0;
|
||||||
saleAmount += pay.getAmount();
|
long saleAmount = 0L;
|
||||||
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.PRE_SALE_COMPLETE && !pay.isCanceled) {
|
int preCount = 0;
|
||||||
preCount++;
|
long preAmount = 0L;
|
||||||
preAmount += pay.getAmount();
|
int refundCount = 0;
|
||||||
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.REFUND) {
|
long refundAmount = 0L;
|
||||||
refundCount++;
|
int caCount = 0;
|
||||||
refundAmount += pay.getAmount();
|
long caAmount = 0L;
|
||||||
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.CASH_ADVANCE) {
|
|
||||||
caCount++;
|
if (list != null && !list.isEmpty()) {
|
||||||
caAmount += pay.getAmount();
|
for (com.utsmyanmar.paylibs.model.PayDetail pay : list) {
|
||||||
|
if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.SALE && !pay.isCanceled) {
|
||||||
|
saleCount++;
|
||||||
|
saleAmount += pay.getAmount();
|
||||||
|
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.PRE_SALE_COMPLETE && !pay.isCanceled) {
|
||||||
|
preCount++;
|
||||||
|
preAmount += pay.getAmount();
|
||||||
|
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.REFUND) {
|
||||||
|
refundCount++;
|
||||||
|
refundAmount += pay.getAmount();
|
||||||
|
} else if (pay.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.CASH_ADVANCE) {
|
||||||
|
caCount++;
|
||||||
|
caAmount += pay.getAmount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
com.utsmyanmar.paylibs.model.TradeData tradeData = com.utsmyanmar.paylibs.utils.params.Params.newTrade(true);
|
com.utsmyanmar.paylibs.model.TradeData tradeData = com.utsmyanmar.paylibs.utils.params.Params.newTrade(true);
|
||||||
com.utsmyanmar.paylibs.model.PayDetail payDetail = tradeData.getPayDetail();
|
com.utsmyanmar.paylibs.model.PayDetail payDetail = tradeData.getPayDetail();
|
||||||
|
|
||||||
String bitmap = com.utsmyanmar.paylibs.utils.iso_utils.BitmapConfig.BPC_SETTLEMENT;
|
String bitmap = com.utsmyanmar.paylibs.utils.iso_utils.BitmapConfig.BPC_SETTLEMENT;
|
||||||
payDetail.setTransType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.name);
|
payDetail.setTransType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.name);
|
||||||
payDetail.setTransactionType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.SETTLEMENT);
|
payDetail.setTransactionType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionType.SETTLEMENT);
|
||||||
payDetail.setProcessCode(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.processCode);
|
payDetail.setProcessCode(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.processCode);
|
||||||
payDetail.setBatchNo(com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation.getInstance().getCurrentBatchNum());
|
payDetail.setBatchNo(com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation.getInstance().getCurrentBatchNum());
|
||||||
|
|
||||||
com.utsmyanmar.paylibs.model.SettleData settleData = new com.utsmyanmar.paylibs.model.SettleData(
|
com.utsmyanmar.paylibs.model.SettleData settleData = new com.utsmyanmar.paylibs.model.SettleData(
|
||||||
saleCount,
|
saleCount, saleAmount, preCount, preAmount, refundCount, refundAmount, caCount, caAmount);
|
||||||
saleAmount,
|
payDetail.setSettleDataObj(settleData);
|
||||||
preCount,
|
|
||||||
preAmount,
|
|
||||||
refundCount,
|
|
||||||
refundAmount,
|
|
||||||
caCount,
|
|
||||||
caAmount
|
|
||||||
);
|
|
||||||
payDetail.setSettleDataObj(settleData);
|
|
||||||
|
|
||||||
long totalAmount = saleAmount + preAmount + refundAmount + caAmount;
|
long totalAmount = saleAmount + preAmount + refundAmount + caAmount;
|
||||||
String settlementData;
|
String settlementData;
|
||||||
if (refundAmount != 0L) {
|
if (refundAmount != 0L) {
|
||||||
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(java.util.Locale.getDefault(), "%012d", Math.abs(subTotal));
|
||||||
|
} else {
|
||||||
|
settlementData = "C" + String.format(java.util.Locale.getDefault(), "%012d", subTotal);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
settlementData = "C" + String.format(java.util.Locale.getDefault(), "%012d", subTotal);
|
settlementData = "C" + String.format(java.util.Locale.getDefault(), "%012d", totalAmount);
|
||||||
}
|
}
|
||||||
} else {
|
payDetail.setSettleData(settlementData);
|
||||||
settlementData = "C" + String.format(java.util.Locale.getDefault(), "%012d", totalAmount);
|
payDetail.setAmount(totalAmount);
|
||||||
}
|
|
||||||
payDetail.setSettleData(settlementData);
|
|
||||||
payDetail.setAmount(totalAmount);
|
|
||||||
|
|
||||||
tradeData.setPayDetail(payDetail);
|
tradeData.setPayDetail(payDetail);
|
||||||
tradeData.setField60(com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation.getInstance().getCurrentBatchNum());
|
tradeData.setField60(com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation.getInstance().getCurrentBatchNum());
|
||||||
|
|
||||||
|
byte[] sendBytes = isoMsgX.buildISOPackets(tradeData, bitmap, com.utsmyanmar.paylibs.utils.MessageType.SETTLEMENT);
|
||||||
|
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, new com.utsmyanmar.paylibs.network.ISOCallback() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(byte[] bytes, int length) {
|
||||||
|
java.util.Map<String, com.utsmyanmar.paylibs.model.MsgField> responseMap = isoMsgX.parseISOPackets(bytes, length);
|
||||||
|
if (responseMap != null) {
|
||||||
|
String resultStr = "";
|
||||||
|
try {
|
||||||
|
resultStr = responseMap.get("F039").getDataStr();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
payDetail.setIsNeedReversal(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
payDetail.setTradeAnswerCode(resultStr);
|
||||||
|
if (TextUtils.equals(resultStr, com.utsmyanmar.paylibs.Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, com.utsmyanmar.paylibs.Constant.ANSWER_CODE_APPROVED)) {
|
||||||
|
payDetail.setIsNeedReversal(false);
|
||||||
|
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
|
||||||
|
payDetail.setIsNeedReversal(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(String msg) {
|
||||||
|
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().switchIp();
|
||||||
|
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
LogUtil.d(TAG, "Auto settlement transaction completed successfully");
|
||||||
|
|
||||||
|
if (list != null && !list.isEmpty()) {
|
||||||
|
for (com.utsmyanmar.paylibs.model.PayDetail p : list) {
|
||||||
|
repository.deletePayDetail(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repository.insertPayDetail(payDetail);
|
||||||
|
|
||||||
byte[] sendBytes = isoMsgX.buildISOPackets(tradeData, bitmap, com.utsmyanmar.paylibs.utils.MessageType.SETTLEMENT);
|
|
||||||
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, new com.utsmyanmar.paylibs.network.ISOCallback() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(byte[] bytes, int length) {
|
|
||||||
java.util.Map<String, com.utsmyanmar.paylibs.model.MsgField> responseMap = isoMsgX.parseISOPackets(bytes, length);
|
|
||||||
if (responseMap != null) {
|
|
||||||
String resultStr = "";
|
|
||||||
try {
|
try {
|
||||||
resultStr = responseMap.get("F039").getDataStr();
|
com.utsmyanmar.paylibs.model.PayDetail cleanPayDetail = new com.utsmyanmar.paylibs.model.PayDetail();
|
||||||
} catch (NullPointerException e) {
|
cleanPayDetail.setTransType(payDetail.getTransType());
|
||||||
|
cleanPayDetail.setTransactionType(payDetail.getTransactionType());
|
||||||
|
cleanPayDetail.setProcessCode(payDetail.getProcessCode());
|
||||||
|
cleanPayDetail.setBatchNo(payDetail.getBatchNo());
|
||||||
|
cleanPayDetail.setSettleData(payDetail.getSettleData());
|
||||||
|
cleanPayDetail.setAmount(payDetail.getAmount());
|
||||||
|
cleanPayDetail.setTradeAnswerCode(payDetail.getTradeAnswerCode());
|
||||||
|
cleanPayDetail.setIsNeedReversal(payDetail.getIsNeedReversal());
|
||||||
|
|
||||||
|
Intent uiIntent = new Intent(getApplicationContext(), com.utsmm.kbz.MainActivity.class);
|
||||||
|
uiIntent.putExtra("AUTO_SETTLEMENT", true);
|
||||||
|
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) {
|
||||||
|
LogUtil.e(TAG, "Error starting MainActivity: " + e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
payDetail.setIsNeedReversal(true);
|
|
||||||
return;
|
try {
|
||||||
}
|
Intent fallbackIntent = new Intent(getApplicationContext(), com.utsmm.kbz.MainActivity.class);
|
||||||
payDetail.setTradeAnswerCode(resultStr);
|
fallbackIntent.putExtra("AUTO_SETTLEMENT", true);
|
||||||
if (TextUtils.equals(resultStr, com.utsmyanmar.paylibs.Constant.ANSWER_CODE_ACCEPT) || TextUtils.equals(resultStr, com.utsmyanmar.paylibs.Constant.ANSWER_CODE_APPROVED)) {
|
fallbackIntent.putExtra("EXTRA_TRANSACTION_TYPE", com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.value);
|
||||||
payDetail.setIsNeedReversal(false);
|
fallbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
} else if (TextUtils.equals(resultStr, "95") || TextUtils.equals(resultStr, "095")) {
|
startActivity(fallbackIntent);
|
||||||
payDetail.setIsNeedReversal(true);
|
|
||||||
|
LogUtil.d(TAG, "MainActivity started with fallback approach");
|
||||||
|
|
||||||
|
} catch (Exception fallbackException) {
|
||||||
|
LogUtil.e(TAG, "Fallback also failed: " + fallbackException.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkIfBothSettlementsComplete();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
repository.getSettlementPOS().observeForever(regularSettlementObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performQRSettlement() {
|
||||||
|
if (qrSettlementCompleted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qrSettlementObserver = new Observer<java.util.List<com.utsmyanmar.paylibs.model.PayDetail>>() {
|
||||||
|
@Override
|
||||||
|
public void onChanged(java.util.List<com.utsmyanmar.paylibs.model.PayDetail> payDetailList) {
|
||||||
|
if (qrSettlementCompleted) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
qrSettlementCompleted = true;
|
||||||
|
|
||||||
@Override
|
// Remove observer immediately to prevent infinite loop
|
||||||
public void onError(String msg) {
|
repository.getTransactionHistory().removeObserver(this);
|
||||||
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().switchIp();
|
|
||||||
com.utsmyanmar.paylibs.network.ISOSocket.getInstance().enqueue(sendBytes, sendBytes.length, false, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (payDetailList != null) {
|
||||||
public void onComplete() {
|
int qrSaleCount = 0;
|
||||||
LogUtil.d(TAG, "Auto settlement transaction completed successfully");
|
long qrSaleAmount = 0;
|
||||||
|
int qrRefundCount = 0;
|
||||||
|
long qrRefundAmount = 0;
|
||||||
|
|
||||||
if (list != null && !list.isEmpty()) {
|
java.util.ArrayList<com.utsmyanmar.paylibs.model.PayDetail> qrTransactionsList = new java.util.ArrayList<>();
|
||||||
for (com.utsmyanmar.paylibs.model.PayDetail p : list) {
|
java.util.ArrayList<com.utsmyanmar.paylibs.model.PayDetail> qrTransListAll = new java.util.ArrayList<>();
|
||||||
repository.deletePayDetail(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repository.insertPayDetail(payDetail);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Remove the non-serializable SettleData object before passing through Intent
|
for (com.utsmyanmar.paylibs.model.PayDetail payDetail : payDetailList) {
|
||||||
// Create a clean copy of PayDetail without the problematic SettleData object
|
// Filter for successful QR transactions only
|
||||||
com.utsmyanmar.paylibs.model.PayDetail cleanPayDetail = new com.utsmyanmar.paylibs.model.PayDetail();
|
if ((payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR.value
|
||||||
cleanPayDetail.setTransType(payDetail.getTransType());
|
|| payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_REFUND.value)
|
||||||
cleanPayDetail.setTransactionType(payDetail.getTransactionType());
|
&& payDetail.getQrTransStatus() == 1) {
|
||||||
cleanPayDetail.setProcessCode(payDetail.getProcessCode());
|
|
||||||
cleanPayDetail.setBatchNo(payDetail.getBatchNo());
|
|
||||||
cleanPayDetail.setSettleData(payDetail.getSettleData());
|
|
||||||
cleanPayDetail.setAmount(payDetail.getAmount());
|
|
||||||
cleanPayDetail.setTradeAnswerCode(payDetail.getTradeAnswerCode());
|
|
||||||
cleanPayDetail.setIsNeedReversal(payDetail.getIsNeedReversal());
|
|
||||||
// Note: Not setting SettleDataObj as it's not serializable
|
|
||||||
|
|
||||||
Intent uiIntent = new Intent(getApplicationContext(), com.utsmm.kbz.MainActivity.class);
|
qrTransactionsList.add(payDetail);
|
||||||
uiIntent.putExtra("AUTO_SETTLEMENT", true);
|
|
||||||
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");
|
if (payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR.value) {
|
||||||
|
qrSaleCount++;
|
||||||
} catch (Exception e) {
|
qrSaleAmount += payDetail.getAmount();
|
||||||
LogUtil.e(TAG, "Error starting MainActivity: " + e.getMessage());
|
} else if (payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_REFUND.value) {
|
||||||
e.printStackTrace();
|
qrRefundCount++;
|
||||||
|
qrRefundAmount += payDetail.getAmount();
|
||||||
// Fallback: start MainActivity without the PayDetail extra
|
}
|
||||||
try {
|
} else if (payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR.value
|
||||||
Intent fallbackIntent = new Intent(getApplicationContext(), com.utsmm.kbz.MainActivity.class);
|
|| payDetail.getTransactionType() == com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_REFUND.value) {
|
||||||
fallbackIntent.putExtra("AUTO_SETTLEMENT", true);
|
// Include all QR transactions for deletion (successful and failed)
|
||||||
fallbackIntent.putExtra("EXTRA_TRANSACTION_TYPE", com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT.value);
|
qrTransListAll.add(payDetail);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
LogUtil.e(TAG, "QR Auto Settlement: Database cursor error - likely due to large data size: " + e);
|
||||||
|
checkIfBothSettlementsComplete();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop the service
|
if (!qrTransactionsList.isEmpty()) {
|
||||||
stopSelf();
|
LogUtil.d(TAG, "Processing QR Auto Settlement with " + qrTransactionsList.size() + " transactions");
|
||||||
|
|
||||||
|
long totalAmount = qrSaleAmount - qrRefundAmount;
|
||||||
|
|
||||||
|
// Increment batch number for QR settlement
|
||||||
|
SystemParamsOperation.getInstance().getIncrementBatchNo();
|
||||||
|
|
||||||
|
// Create settlement data for QR transactions
|
||||||
|
com.utsmyanmar.paylibs.model.SettleData settleData = new com.utsmyanmar.paylibs.model.SettleData(
|
||||||
|
qrSaleCount, qrSaleAmount, 0, 0L, qrRefundCount, qrRefundAmount, 0, 0L);
|
||||||
|
|
||||||
|
com.utsmyanmar.paylibs.model.TradeData tradeData = com.utsmyanmar.paylibs.utils.params.Params.newTrade(false);
|
||||||
|
com.utsmyanmar.paylibs.model.PayDetail payDetail = tradeData.getPayDetail();
|
||||||
|
payDetail.setSettleDataObj(settleData);
|
||||||
|
payDetail.setTransactionType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT.value);
|
||||||
|
payDetail.setTransType(com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT.name);
|
||||||
|
payDetail.setAmount(totalAmount);
|
||||||
|
payDetail.setTradeAnswerCode("000");
|
||||||
|
payDetail.setBatchNo(SystemParamsOperation.getInstance().getCurrentBatchNum());
|
||||||
|
|
||||||
|
// Insert QR settlement record
|
||||||
|
repository.insertPayDetail(payDetail);
|
||||||
|
|
||||||
|
// Delete settled QR transactions
|
||||||
|
for (com.utsmyanmar.paylibs.model.PayDetail pay : qrTransactionsList) {
|
||||||
|
repository.deletePayDetail(pay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete all other QR transactions (failed ones)
|
||||||
|
for (com.utsmyanmar.paylibs.model.PayDetail pay : qrTransListAll) {
|
||||||
|
repository.deletePayDetail(pay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push e-receipt data
|
||||||
|
try {
|
||||||
|
com.utsmyanmar.baselib.network.model.e_receipt.EReceiptRequest request =
|
||||||
|
com.utsmm.kbz.util.EReceiptUtil.getInstance().generateQRSettlement(payDetail);
|
||||||
|
LogUtil.d(TAG, "QR Settlement e-receipt data prepared");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.e(TAG, "Error preparing QR settlement e-receipt: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Start MainActivity with QR settlement data for automatic printing
|
||||||
|
Intent uiIntent = new Intent(getApplicationContext(), com.utsmm.kbz.MainActivity.class);
|
||||||
|
uiIntent.putExtra("AUTO_QR_SETTLEMENT", true);
|
||||||
|
uiIntent.putExtra("EXTRA_TRANSACTION_TYPE", com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.MMQR_SETTLEMENT.value);
|
||||||
|
uiIntent.putExtra("QR_SALE_COUNT", qrSaleCount);
|
||||||
|
uiIntent.putExtra("QR_SALE_AMOUNT", qrSaleAmount);
|
||||||
|
uiIntent.putExtra("QR_REFUND_COUNT", qrRefundCount);
|
||||||
|
uiIntent.putExtra("QR_REFUND_AMOUNT", qrRefundAmount);
|
||||||
|
uiIntent.putExtra("QR_TOTAL_AMOUNT", totalAmount);
|
||||||
|
uiIntent.putExtra("QR_TRANS_LIST", qrTransactionsList);
|
||||||
|
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) {
|
||||||
|
LogUtil.e(TAG, "Error starting MainActivity for QR settlement: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
LogUtil.d(TAG, "QR Auto Settlement completed successfully");
|
||||||
|
} else {
|
||||||
|
LogUtil.d(TAG, "No QR transactions found for auto settlement");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
checkIfBothSettlementsComplete();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
repository.getTransactionHistory().observeForever(qrSettlementObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIfBothSettlementsComplete() {
|
||||||
|
// Stop service only when both settlements are processed (or skipped if no data)
|
||||||
|
if (regularSettlementCompleted && qrSettlementCompleted) {
|
||||||
|
LogUtil.d(TAG, "Both settlements completed, stopping service");
|
||||||
|
stopSelf();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
handler = new Handler();
|
handler = new Handler();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -278,4 +425,19 @@ public class AutoSettleService extends Service {
|
|||||||
public boolean onUnbind(Intent intent) {
|
public boolean onUnbind(Intent intent) {
|
||||||
return super.onUnbind(intent);
|
return super.onUnbind(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
// Clean up observers to prevent memory leaks
|
||||||
|
if (regularSettlementObserver != null && repository != null) {
|
||||||
|
repository.getSettlementPOS().removeObserver(regularSettlementObserver);
|
||||||
|
}
|
||||||
|
if (qrSettlementObserver != null && repository != null) {
|
||||||
|
repository.getTransactionHistory().removeObserver(qrSettlementObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogUtil.d(TAG, "AutoSettleService destroyed and cleaned up");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +113,8 @@ public class TransactionResultFragment extends DataBindingFragment implements Da
|
|||||||
}
|
}
|
||||||
if (resultStr.equals(Constant.ANSWER_CODE_ACCEPT) || resultStr.equals(Constant.ANSWER_CODE_APPROVED)) {
|
if (resultStr.equals(Constant.ANSWER_CODE_ACCEPT) || resultStr.equals(Constant.ANSWER_CODE_APPROVED)) {
|
||||||
/* ISO 8583 RESPONSE */
|
/* ISO 8583 RESPONSE */
|
||||||
if(sharedViewModel.payDetail.getValue().getTransactionType() != TransactionsType.SETTLEMENT.value) {
|
if(sharedViewModel.payDetail.getValue().getTransactionType() != TransactionsType.SETTLEMENT.value
|
||||||
|
&& sharedViewModel.payDetail.getValue().getTransactionType() != TransactionsType.MMQR_SETTLEMENT.value) {
|
||||||
|
|
||||||
if(SystemParamsOperation.getInstance().isAlertSound()) {
|
if(SystemParamsOperation.getInstance().isAlertSound()) {
|
||||||
startSound(getResourceString(R.string.txt_audio_thank_you));
|
startSound(getResourceString(R.string.txt_audio_thank_you));
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import com.utsmm.kbz.util.tms.TMSUtil;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
@ -219,7 +220,7 @@ 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();
|
||||||
// scheduleAutoSettlement();
|
scheduleAutoSettlement();
|
||||||
navigateToMain();
|
navigateToMain();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -279,10 +280,12 @@ public class TMSProcessFragment extends DataBindingFragment {
|
|||||||
LogUtil.d(TAG, "Current time: " + new java.util.Date(currentTime).toString());
|
LogUtil.d(TAG, "Current time: " + new java.util.Date(currentTime).toString());
|
||||||
LogUtil.d(TAG, "Initial trigger time: " + new java.util.Date(triggerAtMillis).toString());
|
LogUtil.d(TAG, "Initial trigger time: " + new java.util.Date(triggerAtMillis).toString());
|
||||||
|
|
||||||
if (currentTime > triggerAtMillis) {
|
if (triggerAtMillis <= currentTime) {
|
||||||
calendar.add(Calendar.DAY_OF_YEAR, 1);
|
calendar.add(Calendar.DAY_OF_YEAR, 1);
|
||||||
triggerAtMillis = calendar.getTimeInMillis();
|
triggerAtMillis = calendar.getTimeInMillis();
|
||||||
LogUtil.d(TAG, "Trigger time is in the past, scheduling for next day: " + new java.util.Date(triggerAtMillis).toString());
|
LogUtil.d(TAG, "Updated trigger time for NEXT DAY: " + new java.util.Date(triggerAtMillis).toString());
|
||||||
|
} else {
|
||||||
|
LogUtil.d(TAG, "Scheduling alarm for TODAY: " + new java.util.Date(triggerAtMillis).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent intent = new Intent(requireContext(), AutoAlarmReceiver.class);
|
Intent intent = new Intent(requireContext(), AutoAlarmReceiver.class);
|
||||||
@ -294,50 +297,33 @@ public class TMSProcessFragment extends DataBindingFragment {
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// For Android 12+ (API 31+), we need to handle exact alarms differently
|
alarmManager.cancel(pendingIntent);
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
|
|
||||||
// Check if the app can schedule exact alarms
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||||
if (alarmManager.canScheduleExactAlarms()) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
|
||||||
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmManager.INTERVAL_DAY, pendingIntent);
|
if (alarmManager.canScheduleExactAlarms()) {
|
||||||
LogUtil.d(TAG, "Auto settlement alarm scheduled successfully for: " + new java.util.Date(triggerAtMillis).toString());
|
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
|
||||||
|
} else {
|
||||||
|
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LogUtil.d(TAG, "App doesn't have permission to schedule exact alarms. Using inexact alarm.");
|
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
|
||||||
// Use inexact alarm as fallback
|
|
||||||
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmManager.INTERVAL_DAY, pendingIntent);
|
|
||||||
LogUtil.d(TAG, "Auto settlement inexact alarm scheduled for: " + new java.util.Date(triggerAtMillis).toString());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For older Android versions
|
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
|
||||||
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmManager.INTERVAL_DAY, pendingIntent);
|
|
||||||
LogUtil.d(TAG, "Auto settlement alarm scheduled successfully for: " + new java.util.Date(triggerAtMillis).toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also try to schedule a test alarm 30 seconds from now for debugging
|
long hoursUntilTrigger = (triggerAtMillis - currentTime) / 1000 / 60 / 60;
|
||||||
long testTriggerTime = currentTime + 30000; // 30 seconds from now
|
long minutesUntilTrigger = ((triggerAtMillis - currentTime) / 1000 / 60) % 60;
|
||||||
Intent testIntent = new Intent(requireContext(), AutoAlarmReceiver.class);
|
LogUtil.d(TAG, "Auto settlement alarm setup completed. Next occurrence: " + new Date(triggerAtMillis).toString());
|
||||||
testIntent.putExtra("TEST_ALARM", true);
|
LogUtil.d(TAG, "Time until next trigger: " + hoursUntilTrigger + " hours, " + minutesUntilTrigger + " minutes");
|
||||||
PendingIntent testPendingIntent = PendingIntent.getBroadcast(
|
|
||||||
requireContext(),
|
|
||||||
1002,
|
|
||||||
testIntent,
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
|
|
||||||
);
|
|
||||||
|
|
||||||
// Schedule test alarm
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
|
|
||||||
if (alarmManager.canScheduleExactAlarms()) {
|
|
||||||
alarmManager.setExact(AlarmManager.RTC_WAKEUP, testTriggerTime, testPendingIntent);
|
|
||||||
} else {
|
|
||||||
alarmManager.set(AlarmManager.RTC_WAKEUP, testTriggerTime, testPendingIntent);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alarmManager.set(AlarmManager.RTC_WAKEUP, testTriggerTime, testPendingIntent);
|
|
||||||
}
|
|
||||||
LogUtil.d(TAG, "Test alarm scheduled for: " + new java.util.Date(testTriggerTime).toString());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.d(TAG, "Error scheduling alarm: " + e.getMessage());
|
LogUtil.e(TAG, "Error scheduling main alarm: " + e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
||||||
|
LogUtil.e(TAG, "Alarm scheduling failed - Check if app has SCHEDULE_EXACT_ALARM permission");
|
||||||
|
LogUtil.e(TAG, "Failed alarm details - Target time: " + new Date(triggerAtMillis).toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -201,7 +201,7 @@ public abstract class BaseXPrint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void dashBreakEnding() {
|
protected void dashBreakEnding() {
|
||||||
printer.appendPrnStr("--------X----------X----------", fontNormal, AlignEnum.LEFT,false);
|
printer.appendPrnStr("--------X----------X---------", fontNormal, AlignEnum.LEFT,false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user