diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen.kt index 64b6cd6..6989f0d 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen.kt @@ -449,7 +449,9 @@ fun DashboardScreen2( Spacer(Modifier.height(12.dp)) SummaryCard( onClickLastSync = onClickLastSync, - lastSyncTime = dashboardUiState.lastSyncTime + lastSyncTime = dashboardUiState.lastSyncTime, + totalSaleCount = dashboardUiState.totalSaleCount, + totalSaleAmount = dashboardUiState.totalSaleAmount ) Spacer(Modifier.height(12.dp)) } @@ -527,7 +529,9 @@ private fun formatRelativeTime(timestamp: Long?, now: Long): String { @Composable private fun SummaryCard( onClickLastSync: () -> Unit, - lastSyncTime: Long? + lastSyncTime: Long?, + totalSaleCount: Int, + totalSaleAmount: Long ) { var now by remember { mutableLongStateOf(System.currentTimeMillis()) } LaunchedEffect(Unit) { @@ -554,9 +558,9 @@ private fun SummaryCard( Row(verticalAlignment = Alignment.CenterVertically) { Column(modifier = Modifier.weight(1f)) { SummaryItem( - title = "Sales Today", - value = "MMK 2,000,000", - subtitle = "47 Transactions", + title = "Total Sale", + value = "MMK ${formatAmount(totalSaleAmount)}", + subtitle = "$totalSaleCount Transactions", icon = Icons.Default.BarChart, iconBg = Color.CrimsonRed ) diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardUiState.kt b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardUiState.kt index 33eb4cb..31205b8 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardUiState.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardUiState.kt @@ -13,5 +13,7 @@ data class TrnxRecord( data class DashboardUiState( val recentTransactions: List = emptyList(), val lastSyncTime: Long? = null, - val carouselUrls: List = emptyList() + val carouselUrls: List = emptyList(), + val totalSaleCount: Int = 0, + val totalSaleAmount: Long = 0L ) diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardViewModel.kt index da5d384..6cd4935 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope import com.utsmyanmar.baselib.repo.Repository import com.utsmyanmar.paylibs.model.PayDetail import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation +import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.MutableStateFlow @@ -29,14 +30,16 @@ class DashboardViewModel @Inject constructor( init { viewModelScope.launch { - repository.getLastTenTransactions().asFlow().collect { payDetails -> - _uiState.update { - it.copy( - recentTransactions = payDetails.map { pd -> pd.toRecord() } - ) - } + repository.getLastTenTransactions().asFlow().collect { payDetails -> + _uiState.update { + it.copy( + recentTransactions = payDetails.map { pd -> pd.toRecord() }, + totalSaleCount = payDetails.totalSaleCount(), + totalSaleAmount = payDetails.totalSaleAmount() + ) } } + } refreshLastSyncTime() loadCarouselUrls() } @@ -58,36 +61,48 @@ class DashboardViewModel @Inject constructor( } private fun PayDetail.toRecord(): TrnxRecord { - val type = transType?.takeIf { it.isNotBlank() }?.let { formatTypeLabel(it) } ?: "Transaction" - val amount = "MMK ${formatAmount(amount)}" - val card = CardNo?.takeIf { it.length >= 4 }?.let { "**** ${it.takeLast(4)}" } ?: "----" - val dt = buildDateTime(TradeDate, TradeTime) + val baseType = transType?.takeIf { it.isNotBlank() }?.let { formatTypeLabel(it) } ?: "Transaction" + val type = if (isCanceled) "Void" else baseType + val amountText = "MMK ${formatAmount(amount)}" + val card = CardNo?.takeIf { it.length >= 4 }?.let { "**** ${it.takeLast(4)}" } ?: "----" + val dt = buildDateTime(TradeDate, TradeTime) val approved = tradeAnswerCode == "00" || approvalCode?.isNotBlank() == true return TrnxRecord( - pid = PID ?: 0L, - typeLabel = type, - amountDisplay= amount, - maskedCard = card, - dateTime = dt, - isVoided = isCanceled, - isApproved = approved + pid = PID ?: 0L, + typeLabel = type, + amountDisplay = amountText, + maskedCard = card, + dateTime = dt, + isVoided = isCanceled, + isApproved = approved ) } - fun formatAmount(amount: Long): String { val scaled = BigDecimal(amount).movePointLeft(2) return DecimalFormat("#,###.00").format(scaled) } + +private fun List.totalSaleCount(): Int = count { it.isSaleTransaction() } + +private fun List.totalSaleAmount(): Long = sumOf { + if (it.isSaleTransaction()) it.amount else 0L +} + +private fun PayDetail.isSaleTransaction(): Boolean { + return transactionType == TransactionsType.SALE.value || + (transactionType == TransactionsType.WAVEPAY.value && qrTransStatus == 1) +} + private fun formatTypeLabel(raw: String): String = when { - raw.contains("SALE", ignoreCase = true) -> "Sale" - raw.contains("VOID", ignoreCase = true) -> "Void" - raw.contains("REFUND", ignoreCase = true) -> "Refund" - raw.contains("SETTLEMENT", ignoreCase = true) -> "Settlement" - raw.contains("PRE", ignoreCase = true) -> "Pre-Auth" - raw.contains("CASH", ignoreCase = true) -> "Cash Out" - raw.contains("WAVE", ignoreCase = true) -> "Wave Pay" + raw.contains("SALE", ignoreCase = true) -> "Sale" + raw.contains("VOID", ignoreCase = true) -> "Void" + raw.contains("REFUND", ignoreCase = true) -> "Refund" + raw.contains("SETTLEMENT", ignoreCase = true) -> "Settlement" + raw.contains("PRE", ignoreCase = true) -> "Pre-Auth" + raw.contains("CASH", ignoreCase = true) -> "Cash Out" + raw.contains("WAVE", ignoreCase = true) -> "Wave Pay" else -> raw.lowercase().replaceFirstChar { it.uppercaseChar() } } diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoViewModel.kt index abc871a..37ecfb0 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoViewModel.kt @@ -67,7 +67,7 @@ class DeviceInfoViewModel : ViewModel() { "PHV?" } } - + private fun getRomVersion():String { return try { android.os.Build.VERSION.RELEASE ?: "UNKNOWN" diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt index 1829cfd..76808ea 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt @@ -1,8 +1,11 @@ package com.mob.utsmyanmar.ui.navigation import android.annotation.SuppressLint +import android.os.Build import androidx.activity.ComponentActivity +import androidx.annotation.RequiresApi import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.platform.LocalContext import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -50,6 +53,7 @@ import com.mob.utsmyanmar.viewmodel.TransProcessViewModel import com.utsmyanmar.paylibs.model.TradeData import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType +@RequiresApi(Build.VERSION_CODES.N) @SuppressLint("ContextCastToActivity") @Composable fun AppNavGraph( @@ -82,10 +86,20 @@ fun AppNavGraph( val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity) val dashboardViewModel: DashboardViewModel = hiltViewModel(activity) val dashboardUiState = dashboardViewModel.uiState.collectAsStateWithLifecycle().value + val tmsSetupViewModel: TmsSetupViewModel = hiltViewModel(); + + LaunchedEffect(tmsSetupViewModel) { + tmsSetupViewModel.onSyncCompleted.collect { + dashboardViewModel.refreshLastSyncTime() + } + } transProcessViewModel.resetTransactionStatus() DashboardScreen2( dashboardUiState = dashboardUiState, + onClickLastSync = { + tmsSetupViewModel.downloadConfigs() + }, onNavigateAmount = { action -> when (action) { "Sale" -> { diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/tms_setup/TmsSetupViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/tms_setup/TmsSetupViewModel.kt index dcfb574..904e98d 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/tms_setup/TmsSetupViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/tms_setup/TmsSetupViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope import com.mob.utsmyanmar.model.sirius.SiriusResponse import com.mob.utsmyanmar.model.sirius.TMSUpdate import com.mob.utsmyanmar.model.sirius.ValidityStatus +import com.mob.utsmyanmar.ui.dashboard.DashboardUiState import com.mob.utsmyanmar.utils.tms.TMSSetupsImpl import com.mob.utsmyanmar.utils.tms.TMSUtil import com.utsmyanmar.baselib.BaseApplication @@ -49,6 +50,7 @@ class TmsSetupViewModel @Inject constructor( ) : ViewModel() { private val _uiState = MutableStateFlow(TmsSetupUiState()) + private val _dashboardUiState = MutableStateFlow(DashboardUiState()) val uiState: StateFlow = _uiState.asStateFlow() private val _navigateToDashboard = MutableSharedFlow() @@ -76,14 +78,15 @@ class TmsSetupViewModel @Inject constructor( it.copy(isLoading = true, isError = false, statusText = "Connecting to TMS server...") } - - val disposable = repository.getParams(buildRequest()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { response -> - _uiState.update { it.copy(statusText = "Applying configuration...") } + _uiState.update { it.copy( + statusText = "Applying configuration...") + } + val appResponse = SiriusResponse( serial = response.serial.orEmpty(), diff --git a/app/src/main/java/com/mob/utsmyanmar/viewmodel/TransProcessViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/viewmodel/TransProcessViewModel.kt index 36b957d..ffbaba7 100644 --- a/app/src/main/java/com/mob/utsmyanmar/viewmodel/TransProcessViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/viewmodel/TransProcessViewModel.kt @@ -1,5 +1,6 @@ package com.mob.utsmyanmar.viewmodel +import android.content.Context import android.text.TextUtils import androidx.lifecycle.ViewModel import com.mob.utsmyanmar.model.TransResultStatus @@ -17,13 +18,15 @@ import com.utsmyanmar.paylibs.utils.PrintStatus import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import javax.inject.Inject @HiltViewModel class TransProcessViewModel @Inject constructor( - private val repository: Repository + private val repository: Repository, + @ApplicationContext private val context: Context ) : ViewModel(), ProcessingTransaction { companion object { @@ -184,6 +187,8 @@ class TransProcessViewModel @Inject constructor( _payDetailResult.value = payDetailRes + stampLastSyncTime() + _transResultStatus.value = TransResultStatus.SUCCESS @@ -252,6 +257,7 @@ class TransProcessViewModel @Inject constructor( repository.insertPayDetail( updateCurrentDateAndTime(payResult) ) + stampLastSyncTime() } override fun processRefundDB(payResult: PayDetail) { @@ -266,6 +272,7 @@ class TransProcessViewModel @Inject constructor( repository.insertPayDetail( updateCurrentDateAndTime(payResult) ) + stampLastSyncTime() } override fun processPreVoidDb(payResult: PayDetail) { @@ -276,6 +283,7 @@ class TransProcessViewModel @Inject constructor( repository.insertPayDetail(updateCurrentDateAndTime(payResult)) + stampLastSyncTime() } override fun processPreCompDb(payResult: PayDetail) { if (oldTransPayDetail?.getAmount() == payResult.getAmount()) { @@ -290,6 +298,7 @@ class TransProcessViewModel @Inject constructor( } } repository.insertPayDetail(updateCurrentDateAndTime(payResult)) + stampLastSyncTime() } override fun processPreCompVoidDb(payResult: PayDetail) { payDetail?.apply { @@ -297,6 +306,7 @@ class TransProcessViewModel @Inject constructor( repository.updatePayDetail(this) } repository.insertPayDetail(updateCurrentDateAndTime(payResult)) + stampLastSyncTime() } /* @@ -371,6 +381,13 @@ class TransProcessViewModel @Inject constructor( }) } + private fun stampLastSyncTime() { + context.getSharedPreferences("mobpos_prefs", Context.MODE_PRIVATE) + .edit() + .putLong("last_sync_time", System.currentTimeMillis()) + .apply() + } + /* * Utils */