diff --git a/.idea/copilot.data.migration.agent.xml b/.idea/copilot.data.migration.agent.xml new file mode 100644 index 0000000..4ea72a9 --- /dev/null +++ b/.idea/copilot.data.migration.agent.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/copilot.data.migration.ask.xml b/.idea/copilot.data.migration.ask.xml new file mode 100644 index 0000000..7ef04e2 --- /dev/null +++ b/.idea/copilot.data.migration.ask.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/copilot.data.migration.edit.xml b/.idea/copilot.data.migration.edit.xml new file mode 100644 index 0000000..8648f94 --- /dev/null +++ b/.idea/copilot.data.migration.edit.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index f1b546e..94f6fad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -88,7 +88,8 @@ kapt { dependencies { implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs') - + implementation libs.androidx.lifecycle.livedata.ktx + implementation libs.androidx.lifecycle.viewmodel.ktx def nav_version = "2.3.2" diff --git a/app/src/main/java/com/utsmm/kbz/MainFragment.java b/app/src/main/java/com/utsmm/kbz/MainFragment.java index 795be0a..ca08238 100644 --- a/app/src/main/java/com/utsmm/kbz/MainFragment.java +++ b/app/src/main/java/com/utsmm/kbz/MainFragment.java @@ -849,31 +849,38 @@ public class MainFragment extends DataBindingFragment { } } - public void onClickQRPay() { - - String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress(); - - if (mainViewModel.payDetailSingle.getValue() != null) { - mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue()); - } -// else if (TMSUtil.getInstance().checkSecHostParams().isStatus() == ValidityStatus.FAILURE) { -// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkSecHostParams().getMessage()); -// } - else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) { - showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet)); - } -// else if (!isValidDomain(mmqrIp)) { -// showDeclineDialog(getResourceString(R.string.txt_please_check_mmqr_ip)); -// } - else { - CurrencyType currencyType = TMSUtil.getInstance().currencyTextToCurrencyType(SystemParamsOperation.getInstance().getSecHostCurrency()); - sharedViewModel.set_currencyText(currencyType.name); - processBatch(); - sharedViewModel.transactionsType.setValue(TransactionsType.MMQR); - navigateToAmount(); - } + public void onClickQRPay(){ + // navigate to new QR Pay fragment + routeId = R.id.action_nav_main_to_qrFragment; + safeNavigateToRouteId(); } +// public void onClickQRPay() { +// +// String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress(); +// +// if (mainViewModel.payDetailSingle.getValue() != null) { +// mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue()); +// } +//// else if (TMSUtil.getInstance().checkSecHostParams().isStatus() == ValidityStatus.FAILURE) { +//// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkSecHostParams().getMessage()); +//// } +// else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) { +// showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet)); +// } +//// else if (!isValidDomain(mmqrIp)) { +//// showDeclineDialog(getResourceString(R.string.txt_please_check_mmqr_ip)); +//// } +// else { +// CurrencyType currencyType = TMSUtil.getInstance().currencyTextToCurrencyType(SystemParamsOperation.getInstance().getSecHostCurrency()); +// sharedViewModel.set_currencyText(currencyType.name); +// processBatch(); +// sharedViewModel.transactionsType.setValue(TransactionsType.MMQR); +// navigateToAmount(); +// +// } +// } + public void onClickSettlement() { if (mainViewModel.payDetailSingle.getValue() != null) { diff --git a/app/src/main/java/com/utsmm/kbz/ui/adapters/QRPayAdapter.java b/app/src/main/java/com/utsmm/kbz/ui/adapters/QRPayAdapter.java new file mode 100644 index 0000000..ce980c2 --- /dev/null +++ b/app/src/main/java/com/utsmm/kbz/ui/adapters/QRPayAdapter.java @@ -0,0 +1,68 @@ +package com.utsmm.kbz.ui.adapters; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.RecyclerView; + +import com.utsmm.kbz.R; +import com.utsmm.kbz.databinding.ItemQrPayButtonBinding; +import com.utsmm.kbz.ui.qr_pay.QRPayItem; + +import java.util.List; + +public class QRPayAdapter extends RecyclerView.Adapter { + + public interface OnItemClickListener { + void onItemClick(int position); + } + + private final List items; + private final OnItemClickListener listener; + + public QRPayAdapter(List item, OnItemClickListener listener) { + this.items = item; + this.listener = listener; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + ItemQrPayButtonBinding binding = DataBindingUtil.inflate( + LayoutInflater.from(parent.getContext()), + R.layout.item_qr_pay_button, + parent, + false + ); + return new ViewHolder(binding); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + QRPayItem item = items.get(position); + holder.binding.setText(item.title); + holder.binding.setIcon(item.icon); + holder.binding.btnItem.setOnClickListener(v -> { + if(listener != null){ + listener.onItemClick(position); + } + }); + } + + @Override + public int getItemCount() { + return items == null ? 0 : items.size(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + final ItemQrPayButtonBinding binding; + public ViewHolder(@NonNull ItemQrPayButtonBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } + } +} + diff --git a/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java new file mode 100644 index 0000000..64908eb --- /dev/null +++ b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java @@ -0,0 +1,387 @@ +package com.utsmm.kbz.ui.qr_pay; + +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import androidx.navigation.fragment.NavHostFragment; + +import com.utsmm.kbz.BR; +import com.utsmm.kbz.MainViewModel; +import com.utsmm.kbz.R; +import com.utsmm.kbz.config.Constants; +import com.utsmm.kbz.ui.adapters.QRPayAdapter; +import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel; +import com.utsmm.kbz.util.Connectivity; +import com.utsmm.kbz.util.tms.TMSUtil; +import com.utsmyanmar.baselib.util.DataBindingConfig; +import com.utsmyanmar.baselib.fragment.DataBindingFragment; +import com.utsmyanmar.paylibs.model.PayDetail; +import com.utsmyanmar.paylibs.utils.POSUtil; +import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation; +import com.utsmyanmar.paylibs.utils.enums.CurrencyType; +import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType; + +import java.util.Date; +import java.util.List; + +public class QRPayFragment extends DataBindingFragment { + + private MainViewModel mainViewModel; + private SharedViewModel sharedViewModel; + private static final int hostId = Constants.NAV_HOST_ID; + private int routeId; + private static final int currentId = R.id.dashboardTransFragment; + + public static QRPayFragment newInstance() { + return new QRPayFragment(); + } + + private QRPayViewModel vm; + private Observer observeLastTrans; + private PayDetail lastPay; + + @Override + public void onResume() { + super.onResume(); + setToolBarTitleWithBackIcon("QR Pay"); + } + + @Override + protected void initViewModel() { + vm = new ViewModelProvider(this).get(QRPayViewModel.class); + mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class); + sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); + } + + @Override + protected DataBindingConfig getDataBindingConfig() { + + List features = List.of( + new QRPayItem("Generate QR", R.drawable.ic_qr_pay), + new QRPayItem("Refund", R.drawable.ic_refund), + new QRPayItem("History", R.drawable.ic_history) + ); + + QRPayAdapter adapter = new QRPayAdapter(features, position -> { + QRPayItem selectedBtn = features.get(position); + switch (selectedBtn.title){ + case "Generate QR": + onClickQRPay(); + break; + case "Refund": + + break; + case "History": + + break; + } + }); + + DataBindingConfig config = new DataBindingConfig(R.layout.fragment_qr_pay, BR.vm, vm); + config.addBindingParam(BR.adapter, adapter); + return config; + } + + @Override + protected int currentId() { + return currentId; + } + + @Override + protected int hostId() { + return hostId; + } + + @Override + protected int routeId() { + return routeId; + } + + public void onClickQRPay() { + + String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress(); + + if (mainViewModel.payDetailSingle.getValue() != null) { + mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue()); + } +// else if (TMSUtil.getInstance().checkSecHostParams().isStatus() == ValidityStatus.FAILURE) { +// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkSecHostParams().getMessage()); +// } + else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) { + showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet)); + } +// else if (!isValidDomain(mmqrIp)) { +// showDeclineDialog(getResourceString(R.string.txt_please_check_mmqr_ip)); +// } + else { + CurrencyType currencyType = TMSUtil.getInstance().currencyTextToCurrencyType(SystemParamsOperation.getInstance().getSecHostCurrency()); + sharedViewModel.set_currencyText(currencyType.name); + processBatch(); + sharedViewModel.transactionsType.setValue(TransactionsType.MMQR); + navigateToAmount(); + } + } + + private void processBatch() { + calculateLastTransaction(); + mainViewModel.observeSettlementPOS(); + observeLastTrans = payDetail -> { + + if(payDetail == null) { + return; + } + +// SystemParamsOperation.getInstance().saveSerialNumber(payDetail.getVoucherNo()); +// SystemParamsOperation.getInstance().saveInvoiceNumber(payDetail.getInvoiceNo()); + + if(lastPay != null) { + Date lastPayDate = POSUtil.getInstance().getDateByString(lastPay.getTransDate()); + Date observePayDate = POSUtil.getInstance().getDateByString(payDetail.getTransDate()); + + if(lastPayDate.compareTo(observePayDate) < 0) { + payDetail = lastPay; + } + } + +// LogUtil.d(TAG,"TransDetail :"+payDetail.getTransType() + "- Trans Time :"+payDetail.getTransDate()); + + if(payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value){ + return; + } + + /* + * saving for api post request, to send in next time. + * */ + SystemParamsOperation.getInstance().setLastTransTime(String.valueOf(payDetail.getTransNum())); + SystemParamsOperation.getInstance().setLastTransName(payDetail.getTransType()); + + + String lastTransDate = payDetail.getTransDate(); + String lastTransTime = payDetail.getTransTime(); + + Date today = POSUtil.getInstance().getCurrentDate(); + Date transDate; + Date current = new Date(System.currentTimeMillis()); + String configTimer = SystemParamsOperation.getInstance().getClearBatchTime(); +// LogUtil.d(TAG,"Config Time :" + configTimer); + String configTime = "23:00"; + int configDay = 10; + + String configRawDay = SystemParamsOperation.getInstance().getClearBatchDay(); + + if(configRawDay != null && !configRawDay.trim().isEmpty()) { + try { + configDay = Integer.parseInt(configRawDay); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + + if(configTimer != null && !configTimer.trim().isEmpty() && checkValidTime(configTimer.trim())) { + configTime = configTimer.trim(); + } + Date configDateTime = POSUtil.getInstance().getDateTime(configTime); + Date yesterdayConfigDateTime = POSUtil.getInstance().getYesterdayConfigDateTime(configTime); + + transDate = POSUtil.getInstance().getDateByString(lastTransDate); + + Date yesterdayDate = POSUtil.getInstance().getYesterdayDate(); + + if(today.compareTo(transDate) == 0) { + +// LogUtil.d(TAG,"Last Trans is Today!"); +// LogUtil.d(TAG,"date current :!"+current); +// LogUtil.d(TAG,"date config :!"+configDateTime); + + // Today + if(current.compareTo(configDateTime) > 0) { + // clear batch and force update param + +// LogUtil.d(TAG,"Last Trans is Today! Config time is passed!"); +// if (!SystemParamsOperation.getInstance().isClearBatch()) { + if (checkSyncTrans() || !SystemParamsOperation.getInstance().isClearBatch() ) { +// LogUtil.d(TAG,"Clearing...."); + if(!SystemParamsOperation.getInstance().getSettlementStatus()) { + clearBatchAndDownload(configDay,payDetail); + } + } + + + } else { +// LogUtil.d(TAG,"Last Trans is Today! Config time is not passed yet....."); + SystemParamsOperation.getInstance().setClearBatch(false); + } + + } else { +// LogUtil.d(TAG,"Last Trans is Before Today!"); + Date yest; + if(configTime.equals("00:00")) { + yest = configDateTime; + } else { + yest = yesterdayConfigDateTime; + } + + + Date lastTransDateTime = POSUtil.getInstance().getDateByTransDateTime(lastTransDate,lastTransTime); +// LogUtil.d(TAG,"Compare Result : "+lastTransDateTime.compareTo(yest)); + + if(yest.compareTo(lastTransDateTime) < 0) { +// LogUtil.d(TAG,"Trans is yesterday, but after config time, no action!"); + } else { +// LogUtil.d(TAG,"Trans is yesterday, before config time,"); +// if(!checkSyncTrans()) { +// LogUtil.d(TAG,"Clearing...."); + if(!SystemParamsOperation.getInstance().getSettlementStatus()) { + clearBatchAndDownload(configDay,payDetail); + } +// } + } + + + + } + }; + if(mainViewModel.lastTrans.hasActiveObservers()) { + mainViewModel.lastTrans.removeObserver(observeLastTrans); + } + mainViewModel.lastTrans.observe(getViewLifecycleOwner(),observeLastTrans); + } + + private void calculateLastTransaction() { + mainViewModel.allTrans.observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(List payDetails) { + if(payDetails == null || payDetails.isEmpty()) { + return; + } + PayDetail tempPay = payDetails.get(0); + for (int i = 0; i < payDetails.size() ; i++) { + + Date tempDate = POSUtil.getInstance().getDateByString(tempPay.getTransDate()); + Date indexDate = POSUtil.getInstance().getDateByString(payDetails.get(i).getTransDate()); + + if(tempDate.compareTo(indexDate) > 0) { + // if before + tempPay = payDetails.get(i); + } + } + + lastPay = tempPay; + +// LogUtil.d(TAG,"Transaction Name : "+tempPay.getTransType()); +// LogUtil.d(TAG,"Transaction Type : "+tempPay.getTransactionType()); +// LogUtil.d(TAG,"Transaction Amount : "+tempPay.getAmount()); +// LogUtil.d(TAG,"Transaction Date/Time : "+tempPay.getTransDate()+"/"+tempPay.getTransTime()); +// LogUtil.d(TAG,"RRN/Trace : "+tempPay.getReferNo()+"/"+tempPay.getVoucherNo()); +// LogUtil.d(TAG,"Transaction is canceled : "+tempPay.isCanceled()); +// LogUtil.d(TAG,"Transaction settlement config : "+tempPay.isSettlementEnabled()); +// LogUtil.d(TAG,"----------------------------------------------------------"); + } + }); + } + + private boolean checkSyncTrans() { + String transDateString = SystemParamsOperation.getInstance().getSyncTransDate(); + Date today = POSUtil.getInstance().getCurrentDate(); + if(transDateString == null || transDateString.isEmpty()) { + return true; + } + Date transDate = POSUtil.getInstance().getDateByString(transDateString); + return today.compareTo(transDate) == 0; + + } + + private void clearBatchAndDownload(int configDay,PayDetail payDetail) { + + + Date yesterday = POSUtil.getInstance().getYesterdayDate(); + Date lastInputDay = POSUtil.getInstance().getLastInputDay(configDay); + mainViewModel.settlementPOS.observe(getViewLifecycleOwner(), list -> { + + Date transDate; + + if(list == null || list.size() == 0) { + return; + } + + for (PayDetail pay:list) { + /* + * To Hold One day transaction! + * */ + + transDate = POSUtil.getInstance().getDateByString(pay.getTransDate()); + + if (pay.getTransactionType() == TransactionsType.SALE.value) { + if(lastInputDay.compareTo(transDate) > 0) { + mainViewModel.deletePayDetail(pay); + } + } else { + if(yesterday.compareTo(transDate) > 0 ) { + mainViewModel.deletePayDetail(pay); + } + } + + + } + + }); + + mainViewModel.deleteTrans.observe(getViewLifecycleOwner(), lists -> { + Date transDate; + if(lists == null || lists.size() == 0) { + return; + } + + for (PayDetail pay:lists) { + /* + * To Hold One day transaction! + * */ + + transDate = POSUtil.getInstance().getDateByString(pay.getTransDate()); +// LogUtil.d(TAG,"Trans Type : "+pay.getTransType()+"<=====> Trans Date :"+pay.getTransDate()); +// LogUtil.d(TAG,"Yesterday Date: "+yesterday.toString()); +// LogUtil.d(TAG,"Compare result :"+yesterday.compareTo(transDate)); + + if(yesterday.compareTo(transDate) > 0) { + mainViewModel.deletePayDetail(pay); + } + + } + }); + + mainViewModel.preAuthTrans.observe(getViewLifecycleOwner(), lists -> { + Date transDate; + if(lists == null || lists.size() == 0) { + return; + } + + for (PayDetail pay:lists) { + + transDate = POSUtil.getInstance().getDateByString(pay.getTransDate()); + + if (lastInputDay.compareTo(transDate) > 0) { + mainViewModel.deletePayDetail(pay); + } + + + } + }); + + /* + * + * Need to think about his problem .... Nov 7, 2024 + * */ + if(!SystemParamsOperation.getInstance().isClearBatch()) { +// downloadParams(payDetail.getTransType(),String.valueOf(payDetail.getTransNum()),TMSUpdate.UPDATE,false); + } + + } + + private void navigateToAmount() { +// routeId = R.id.action_nav_main_to_inputAmountFragment; +// safeNavigateToRouteId(); + NavHostFragment.findNavController(this) + .navigate(R.id.action_qrFragment_to_inputAmountFragment); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayItem.java b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayItem.java new file mode 100644 index 0000000..e7af619 --- /dev/null +++ b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayItem.java @@ -0,0 +1,11 @@ +package com.utsmm.kbz.ui.qr_pay; + +public class QRPayItem { + public String title; + public int icon; + + public QRPayItem(String title, int icon) { + this.title = title; + this.icon = icon; + } +} diff --git a/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayViewModel.java b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayViewModel.java new file mode 100644 index 0000000..0adab25 --- /dev/null +++ b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayViewModel.java @@ -0,0 +1,17 @@ +package com.utsmm.kbz.ui.qr_pay; + +import androidx.lifecycle.ViewModel; + +public class QRPayViewModel extends ViewModel { + public void generateQR(){ + + } + + public void refundQR(){ + + } + + public void historyQR(){ + + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_qr_pay.xml b/app/src/main/res/layout/fragment_qr_pay.xml new file mode 100644 index 0000000..0c09527 --- /dev/null +++ b/app/src/main/res/layout/fragment_qr_pay.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_qr_pay_button.xml b/app/src/main/res/layout/item_qr_pay_button.xml new file mode 100644 index 0000000..d84fe47 --- /dev/null +++ b/app/src/main/res/layout/item_qr_pay_button.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 8085dac..d9e88da 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -141,6 +141,9 @@ + - - + + + + \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index af7dd89..efb2740 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,9 @@ coreKtx = "1.17.0" hilt = "2.51.1" androidx-hilt = "1.2.0" nav = "2.5.0" +legacySupportV4 = "1.0.0" +lifecycleLivedataKtx = "2.9.4" +lifecycleViewmodelKtx = "2.9.4" [libraries] junit = { group = "junit", name = "junit", version.ref = "junit" } @@ -25,6 +28,9 @@ core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" } androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "androidx-hilt" } +androidx-legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" } +androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" } +androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }