Settlement Screen init
This commit is contained in:
parent
767456b29a
commit
af917520b6
@ -0,0 +1,11 @@
|
|||||||
|
package com.mob.utsmyanmar.model
|
||||||
|
|
||||||
|
enum class TransactionStatus {
|
||||||
|
ON_SUCCESS,
|
||||||
|
ON_REVERSAL,
|
||||||
|
ON_BATCH_UPLOAD,
|
||||||
|
ON_FAIL,
|
||||||
|
ON_ERROR,
|
||||||
|
ON_SECONDARY,
|
||||||
|
ON_DONE
|
||||||
|
}
|
||||||
@ -38,6 +38,7 @@ import androidx.compose.material3.CardDefaults
|
|||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.DrawerValue
|
||||||
import androidx.compose.material3.ModalDrawerSheet
|
import androidx.compose.material3.ModalDrawerSheet
|
||||||
import androidx.compose.material3.ModalNavigationDrawer
|
import androidx.compose.material3.ModalNavigationDrawer
|
||||||
import androidx.compose.material3.NavigationDrawerItem
|
import androidx.compose.material3.NavigationDrawerItem
|
||||||
@ -85,6 +86,7 @@ fun DashboardScreen2(
|
|||||||
onNavigateAmount: (String) -> Unit = {},
|
onNavigateAmount: (String) -> Unit = {},
|
||||||
onNavigateSignOn: () -> Unit = {},
|
onNavigateSignOn: () -> Unit = {},
|
||||||
onNavigateSeeMore: () -> Unit = {},
|
onNavigateSeeMore: () -> Unit = {},
|
||||||
|
onNavigateSettlement: () -> Unit = {},
|
||||||
deviceInfoViewModel: DeviceInfoViewModel = viewModel()
|
deviceInfoViewModel: DeviceInfoViewModel = viewModel()
|
||||||
) {
|
) {
|
||||||
val deviceInfo by deviceInfoViewModel.uiState.collectAsState()
|
val deviceInfo by deviceInfoViewModel.uiState.collectAsState()
|
||||||
@ -92,7 +94,7 @@ fun DashboardScreen2(
|
|||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
deviceInfoViewModel.loadDeviceInfo();
|
deviceInfoViewModel.loadDeviceInfo();
|
||||||
}
|
}
|
||||||
val drawerState = rememberDrawerState(initialValue = androidx.compose.material3.DrawerValue.Closed)
|
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val mainHandler = remember { Handler(Looper.getMainLooper()) }
|
val mainHandler = remember { Handler(Looper.getMainLooper()) }
|
||||||
var showHostActionDialog by remember { mutableStateOf(false) }
|
var showHostActionDialog by remember { mutableStateOf(false) }
|
||||||
@ -301,7 +303,8 @@ fun DashboardScreen2(
|
|||||||
MenuGrid(
|
MenuGrid(
|
||||||
onNavigateAmount = onNavigateAmount,
|
onNavigateAmount = onNavigateAmount,
|
||||||
onNavigateSignOn = onNavigateSignOn,
|
onNavigateSignOn = onNavigateSignOn,
|
||||||
onNavigateSeeMore = onNavigateSeeMore
|
onNavigateSeeMore = onNavigateSeeMore,
|
||||||
|
onNavigateSettlement = onNavigateSettlement
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,7 +499,8 @@ private fun IconCircle(
|
|||||||
private fun MenuGrid(
|
private fun MenuGrid(
|
||||||
onNavigateAmount: (String) -> Unit,
|
onNavigateAmount: (String) -> Unit,
|
||||||
onNavigateSignOn: () -> Unit,
|
onNavigateSignOn: () -> Unit,
|
||||||
onNavigateSeeMore: () -> Unit
|
onNavigateSeeMore: () -> Unit,
|
||||||
|
onNavigateSettlement: () -> Unit
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
@ -520,7 +524,12 @@ private fun MenuGrid(
|
|||||||
Modifier.weight(1f),
|
Modifier.weight(1f),
|
||||||
onClick = onNavigateSignOn
|
onClick = onNavigateSignOn
|
||||||
)
|
)
|
||||||
MenuCard("Settlement", Icons.Default.Wallet, Modifier.weight(1f))
|
MenuCard(
|
||||||
|
"Settlement",
|
||||||
|
Icons.Default.Wallet,
|
||||||
|
Modifier.weight(1f),
|
||||||
|
onClick = onNavigateSettlement
|
||||||
|
)
|
||||||
MenuCard(
|
MenuCard(
|
||||||
"See More",
|
"See More",
|
||||||
Icons.Default.GridView,
|
Icons.Default.GridView,
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import com.mob.utsmyanmar.ui.print_receipt.PrintReceiptScreen
|
|||||||
import com.mob.utsmyanmar.ui.sign_on.SignOnResultScreen
|
import com.mob.utsmyanmar.ui.sign_on.SignOnResultScreen
|
||||||
import com.mob.utsmyanmar.ui.sign_on.SignOnRoute
|
import com.mob.utsmyanmar.ui.sign_on.SignOnRoute
|
||||||
import com.mob.utsmyanmar.ui.sending_to_host.SendingToHostRoute
|
import com.mob.utsmyanmar.ui.sending_to_host.SendingToHostRoute
|
||||||
|
import com.mob.utsmyanmar.ui.settlement.SettlementScreen
|
||||||
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultRoute
|
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultRoute
|
||||||
import com.mob.utsmyanmar.ui.sale_void.TranDetailPage
|
import com.mob.utsmyanmar.ui.sale_void.TranDetailPage
|
||||||
import com.mob.utsmyanmar.ui.sale_void.VoidViewModel
|
import com.mob.utsmyanmar.ui.sale_void.VoidViewModel
|
||||||
@ -63,6 +64,11 @@ fun AppNavGraph(
|
|||||||
navController.navigate(Routes.SeeMore.route) {
|
navController.navigate(Routes.SeeMore.route) {
|
||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onNavigateSettlement = {
|
||||||
|
navController.navigate(Routes.Settlement.route) {
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -98,6 +104,24 @@ fun AppNavGraph(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
composable(Routes.Settlement.route) {
|
||||||
|
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
|
||||||
|
|
||||||
|
SettlementScreen(
|
||||||
|
sharedViewModel = sharedViewModel,
|
||||||
|
onBack = { navController.popBackStack() },
|
||||||
|
onStartSettlement = {
|
||||||
|
sharedViewModel.transactionsType.value = com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType.SETTLEMENT
|
||||||
|
navController.navigate(Routes.SendingToHost.route) {
|
||||||
|
popUpTo(Routes.Settlement.route) {
|
||||||
|
inclusive = true
|
||||||
|
}
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
composable(
|
composable(
|
||||||
route = Routes.VoidTranDetail.route,
|
route = Routes.VoidTranDetail.route,
|
||||||
arguments = listOf(
|
arguments = listOf(
|
||||||
|
|||||||
@ -8,6 +8,7 @@ sealed class Routes(val route: String) {
|
|||||||
fun createRoute(action: String): String = "amount/${Uri.encode(action)}"
|
fun createRoute(action: String): String = "amount/${Uri.encode(action)}"
|
||||||
}
|
}
|
||||||
data object SeeMore : Routes("see_more")
|
data object SeeMore : Routes("see_more")
|
||||||
|
data object Settlement : Routes("settlement")
|
||||||
data object VoidTrace : Routes("void_trace")
|
data object VoidTrace : Routes("void_trace")
|
||||||
data object VoidTranDetail : Routes("void_tran_detail/{trace}") {
|
data object VoidTranDetail : Routes("void_tran_detail/{trace}") {
|
||||||
fun createRoute(trace: String): String = "void_tran_detail/${Uri.encode(trace)}"
|
fun createRoute(trace: String): String = "void_tran_detail/${Uri.encode(trace)}"
|
||||||
|
|||||||
@ -0,0 +1,194 @@
|
|||||||
|
package com.mob.utsmyanmar.ui.settlement
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.mob.utsmyanmar.ui.components.appbar.AppBar
|
||||||
|
import com.mob.utsmyanmar.ui.theme.Color
|
||||||
|
import com.mob.utsmyanmar.viewmodel.SharedViewModel
|
||||||
|
import com.utsmyanmar.paylibs.model.PayDetail
|
||||||
|
import com.utsmyanmar.paylibs.utils.POSUtil
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettlementScreen(
|
||||||
|
sharedViewModel: SharedViewModel,
|
||||||
|
onBack: () -> Unit,
|
||||||
|
onStartSettlement: () -> Unit
|
||||||
|
) {
|
||||||
|
val records by sharedViewModel.getSettlementRecords().observeAsState(emptyList())
|
||||||
|
val totalAmount = records.sumOf { it.amount }
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
containerColor = Color.IvoryBeige,
|
||||||
|
topBar = {
|
||||||
|
AppBar(
|
||||||
|
title = "Settlement",
|
||||||
|
icon = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
|
onIconClick = onBack
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.padding(18.dp)) {
|
||||||
|
Text(
|
||||||
|
text = "Settlement Summary",
|
||||||
|
color = Color.LegacyRed,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
|
SummaryRow("Record Count", records.size.toString())
|
||||||
|
SummaryRow("Total Amount", POSUtil.getInstance().formatAmount(totalAmount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Unsettled Records",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.White)
|
||||||
|
) {
|
||||||
|
if (records.isEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = "No records available for settlement.",
|
||||||
|
color = Color.Gray,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
modifier = Modifier.padding(18.dp)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(0.dp)
|
||||||
|
) {
|
||||||
|
items(records) { record ->
|
||||||
|
SettlementRecordRow(record = record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = onStartSettlement,
|
||||||
|
enabled = records.isNotEmpty(),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(56.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = Color.LegacyRed,
|
||||||
|
contentColor = Color.White
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text("Start Settlement")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SummaryRow(
|
||||||
|
label: String,
|
||||||
|
value: String
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
color = Color.Gray,
|
||||||
|
fontSize = 13.sp
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = value,
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 13.sp,
|
||||||
|
fontWeight = FontWeight.Medium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SettlementRecordRow(record: PayDetail) {
|
||||||
|
Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = record.transType.ifBlank { "UNKNOWN" },
|
||||||
|
color = Color.LegacyRed,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = POSUtil.getInstance().formatAmount(record.amount),
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Trace ${record.voucherNo.ifBlank { "-" }}",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Card ${record.cardNo.ifBlank { "-" }}",
|
||||||
|
color = Color.Gray,
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
HorizontalDivider(color = Color.Gray.copy(alpha = 0.25f))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,440 @@
|
|||||||
|
package com.mob.utsmyanmar.ui.settlement
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.mob.utsmyanmar.config.Constants
|
||||||
|
import com.mob.utsmyanmar.model.SettlementType
|
||||||
|
import com.mob.utsmyanmar.model.TransactionStatus
|
||||||
|
import com.utsmyanmar.baselib.repo.Repository
|
||||||
|
import com.utsmyanmar.paylibs.Constant
|
||||||
|
import com.utsmyanmar.paylibs.batch_upload.BatchListener
|
||||||
|
import com.utsmyanmar.paylibs.batch_upload.BatchUploadProcess
|
||||||
|
import com.utsmyanmar.paylibs.isobuilder.ISOMode
|
||||||
|
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.MessageType
|
||||||
|
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 dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import sunmi.sunmiui.utils.LogUtil
|
||||||
|
import java.util.Locale
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
data class SettlementUiState(
|
||||||
|
val saleCount: Int = 0,
|
||||||
|
val saleAmount: Long = 0L,
|
||||||
|
|
||||||
|
val preCount: Int = 0,
|
||||||
|
val preAmount: Long = 0L,
|
||||||
|
|
||||||
|
val refundCount: Int = 0,
|
||||||
|
val refundAmount: Long = 0L,
|
||||||
|
|
||||||
|
val caCount: Int = 0,
|
||||||
|
val caAmount: Long = 0L,
|
||||||
|
|
||||||
|
val settlementType: SettlementType? = null,
|
||||||
|
val isNoData: Boolean = false,
|
||||||
|
val isSentData: Boolean = false,
|
||||||
|
val bottomLayout: Int = 0,
|
||||||
|
|
||||||
|
val status: TransactionStatus? = null,
|
||||||
|
val isLoading: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed interface SettlementEvent {
|
||||||
|
data class ShowStatus(val status: TransactionStatus) : SettlementEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class SettlementViewModel @Inject constructor(
|
||||||
|
private val repository: Repository
|
||||||
|
) : ViewModel() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = SettlementViewModel::class.java.simpleName
|
||||||
|
}
|
||||||
|
|
||||||
|
private var payDetail: PayDetail? = null
|
||||||
|
private var payDetails: List<PayDetail>? = null
|
||||||
|
|
||||||
|
private val deleteTrans = arrayListOf<PayDetail>()
|
||||||
|
|
||||||
|
private var flag = false
|
||||||
|
private var errorFlag = false
|
||||||
|
private var isSecondCall = false
|
||||||
|
private var batchIndex = 0
|
||||||
|
|
||||||
|
private var bitmap = ""
|
||||||
|
|
||||||
|
private val isoMsgX: ISOMsgX =
|
||||||
|
ISOMsgX.ISOMsgXBuilder(
|
||||||
|
ISOVersion.VERSION_1993,
|
||||||
|
ISOMode.BOTH_HEADER_TPDU,
|
||||||
|
HostName.BPC
|
||||||
|
).build()
|
||||||
|
|
||||||
|
private val _uiState = MutableStateFlow(SettlementUiState())
|
||||||
|
val uiState = _uiState.asStateFlow()
|
||||||
|
|
||||||
|
private val _events = Channel<SettlementEvent>(Channel.BUFFERED)
|
||||||
|
val events = _events.receiveAsFlow()
|
||||||
|
|
||||||
|
fun getLastSettlement(voucherNo: String): LiveData<List<PayDetail>> {
|
||||||
|
return repository.getLastSettlement(voucherNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSettlement(): LiveData<List<PayDetail>> {
|
||||||
|
return repository.getSettlement()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSettlementPOS(): LiveData<List<PayDetail>> {
|
||||||
|
return repository.getSettlementPOS()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDeleteTrans(batchNo: String): LiveData<List<PayDetail>> {
|
||||||
|
return repository.getDeleteTrans(batchNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAdditionalSettlementPOS(): LiveData<List<PayDetail>> {
|
||||||
|
return repository.getAdditionalSettlementPOS(
|
||||||
|
SystemParamsOperation.getInstance().getCurrentBatchNum()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setPayDetails(list: List<PayDetail>) {
|
||||||
|
payDetails = list
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSettlementSummary(
|
||||||
|
saleCount: Int,
|
||||||
|
saleAmount: Long,
|
||||||
|
preCount: Int,
|
||||||
|
preAmount: Long,
|
||||||
|
refundCount: Int,
|
||||||
|
refundAmount: Long,
|
||||||
|
caCount: Int,
|
||||||
|
caAmount: Long
|
||||||
|
) {
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(
|
||||||
|
saleCount = saleCount,
|
||||||
|
saleAmount = saleAmount,
|
||||||
|
preCount = preCount,
|
||||||
|
preAmount = preAmount,
|
||||||
|
refundCount = refundCount,
|
||||||
|
refundAmount = refundAmount,
|
||||||
|
caCount = caCount,
|
||||||
|
caAmount = caAmount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSettlementType(type: SettlementType) {
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(settlementType = type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updatePayDetail(payDetail: PayDetail) {
|
||||||
|
repository.updatePayDetail(payDetail)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun insertPayDetail(payDetail: PayDetail) {
|
||||||
|
repository.insertPayDetail(payDetail)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateDB() {
|
||||||
|
payDetails?.forEach { pay ->
|
||||||
|
repository.deletePayDetail(pay)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTrans.forEach { pay ->
|
||||||
|
repository.deletePayDetail(pay)
|
||||||
|
}
|
||||||
|
|
||||||
|
payDetails = emptyList()
|
||||||
|
deleteTrans.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startSettlementProcess() {
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(isLoading = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemParamsOperation.getInstance().getIncrementBatchNo()
|
||||||
|
|
||||||
|
requestOnlineProcessSettlement()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startPrintSettlementProcess() {
|
||||||
|
// PrintReceipt.getInstance().printSettlementReceiptPOS(...)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testServiceClass() {
|
||||||
|
LogUtil.d(TAG, "SettlementViewModel works!")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun requestOnlineProcessSettlement() {
|
||||||
|
val state = _uiState.value
|
||||||
|
|
||||||
|
val hostName = HostName.BPC
|
||||||
|
val field60 = SystemParamsOperation.getInstance().getCurrentBatchNum()
|
||||||
|
|
||||||
|
val sale2Count = state.saleCount + state.preCount
|
||||||
|
val sale2Amount = state.saleAmount + state.preAmount
|
||||||
|
|
||||||
|
val totalSaleCount = String.format(Locale.getDefault(), "%03d", sale2Count)
|
||||||
|
val totalSaleAmount = String.format(Locale.getDefault(), "%010d00", sale2Amount)
|
||||||
|
|
||||||
|
val totalRefundCount = String.format(Locale.getDefault(), "%03d", state.refundCount)
|
||||||
|
val totalRefundAmount = String.format(
|
||||||
|
Locale.getDefault(),
|
||||||
|
"%010d00",
|
||||||
|
if (state.refundAmount == 0L) 0 else state.refundAmount
|
||||||
|
)
|
||||||
|
|
||||||
|
val totalDebitSaleCount = String.format(Locale.getDefault(), "%03d", state.caCount)
|
||||||
|
val totalDebitSaleAmount = String.format(
|
||||||
|
Locale.getDefault(),
|
||||||
|
"%010d00",
|
||||||
|
if (state.caAmount == 0L) 0 else state.caAmount
|
||||||
|
)
|
||||||
|
|
||||||
|
val totalERefundCount = String.format(Locale.getDefault(), "%03d", 0)
|
||||||
|
val totalERefundAmount = String.format(Locale.getDefault(), "%010d00", 0)
|
||||||
|
|
||||||
|
val tradeData = Params.newTrade(true)
|
||||||
|
val currentPayDetail = tradeData.payDetail
|
||||||
|
|
||||||
|
payDetail = currentPayDetail
|
||||||
|
|
||||||
|
bitmap = BitmapConfig.BPC_SETTLEMENT
|
||||||
|
|
||||||
|
currentPayDetail.transType = TransactionsType.SETTLEMENT.name
|
||||||
|
currentPayDetail.transactionType = TransactionType.SETTLEMENT
|
||||||
|
|
||||||
|
if (!flag) {
|
||||||
|
currentPayDetail.processCode = TransactionsType.SETTLEMENT.processCode
|
||||||
|
} else {
|
||||||
|
bitmap = BitmapConfig.BPC_SETTLEMENT_TRAILER
|
||||||
|
currentPayDetail.processCode = "910000"
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPayDetail.batchNo = SystemParamsOperation.getInstance().getCurrentBatchNum()
|
||||||
|
|
||||||
|
currentPayDetail.settleList =
|
||||||
|
"${state.saleCount}:${state.saleAmount}-" +
|
||||||
|
"${state.caCount}:${state.caAmount}-" +
|
||||||
|
"${state.refundCount}:${state.refundAmount}-" +
|
||||||
|
"${state.preCount}:${state.preAmount}"
|
||||||
|
|
||||||
|
val settleData = SettleData(
|
||||||
|
state.saleCount,
|
||||||
|
state.saleAmount,
|
||||||
|
state.preCount,
|
||||||
|
state.preAmount,
|
||||||
|
state.refundCount,
|
||||||
|
state.refundAmount,
|
||||||
|
state.caCount,
|
||||||
|
state.caAmount
|
||||||
|
)
|
||||||
|
|
||||||
|
currentPayDetail.settleDataObj = settleData
|
||||||
|
|
||||||
|
if (hostName == HostName.BPC) {
|
||||||
|
val totalAmount =
|
||||||
|
state.saleAmount + state.preAmount + state.refundAmount + state.caAmount
|
||||||
|
|
||||||
|
val settlementData = if (state.refundAmount != 0L) {
|
||||||
|
val creditTotal = state.saleAmount + state.preAmount + state.caAmount
|
||||||
|
val subTotal = creditTotal - state.refundAmount
|
||||||
|
|
||||||
|
if (subTotal < 0L) {
|
||||||
|
"D" + String.format(Locale.getDefault(), "%012d", kotlin.math.abs(subTotal))
|
||||||
|
} else {
|
||||||
|
"C" + String.format(Locale.getDefault(), "%012d", subTotal)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"C" + String.format(Locale.getDefault(), "%012d", totalAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPayDetail.settleData = settlementData
|
||||||
|
currentPayDetail.amount = totalAmount
|
||||||
|
} else {
|
||||||
|
currentPayDetail.settleData =
|
||||||
|
totalSaleCount +
|
||||||
|
totalSaleAmount +
|
||||||
|
totalRefundCount +
|
||||||
|
totalRefundAmount +
|
||||||
|
totalDebitSaleCount +
|
||||||
|
totalDebitSaleAmount +
|
||||||
|
totalERefundCount +
|
||||||
|
totalERefundAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
tradeData.payDetail = currentPayDetail
|
||||||
|
tradeData.field60 = field60
|
||||||
|
|
||||||
|
val sendBytes = isoMsgX.buildISOPackets(
|
||||||
|
tradeData,
|
||||||
|
bitmap,
|
||||||
|
MessageType.SETTLEMENT
|
||||||
|
)
|
||||||
|
|
||||||
|
LogUtil.d(TAG, "Starting SETTLEMENT process...")
|
||||||
|
|
||||||
|
ISOSocket.getInstance().enqueue(
|
||||||
|
sendBytes,
|
||||||
|
sendBytes.size,
|
||||||
|
false,
|
||||||
|
object : ISOCallback {
|
||||||
|
|
||||||
|
override fun onReceive(bytes: ByteArray, length: Int) {
|
||||||
|
val responseMap: Map<String, MsgField>? =
|
||||||
|
isoMsgX.parseISOPackets(bytes, length)
|
||||||
|
|
||||||
|
if (responseMap != null) {
|
||||||
|
val resultStr = try {
|
||||||
|
responseMap["F039"]?.dataStr.orEmpty()
|
||||||
|
} catch (e: NullPointerException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
currentPayDetail.isNeedReversal = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPayDetail.tradeAnswerCode = resultStr
|
||||||
|
|
||||||
|
when {
|
||||||
|
resultStr == Constant.ANSWER_CODE_ACCEPT ||
|
||||||
|
resultStr == Constant.ANSWER_CODE_APPROVED -> {
|
||||||
|
currentPayDetail.isNeedReversal = false
|
||||||
|
}
|
||||||
|
|
||||||
|
resultStr == "95" || resultStr == "095" -> {
|
||||||
|
currentPayDetail.isNeedReversal = !flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errorFlag = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(msg: String) {
|
||||||
|
if (msg != Constants.REVERSAL) {
|
||||||
|
if (!isSecondCall) {
|
||||||
|
ISOSocket.getInstance().switchIp()
|
||||||
|
|
||||||
|
postStatus(TransactionStatus.ON_SECONDARY)
|
||||||
|
|
||||||
|
isSecondCall = true
|
||||||
|
requestOnlineProcessSettlement()
|
||||||
|
} else {
|
||||||
|
postStatus(TransactionStatus.ON_ERROR)
|
||||||
|
|
||||||
|
currentPayDetail.isNeedReversal = true
|
||||||
|
isSecondCall = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
postStatus(TransactionStatus.ON_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
if (currentPayDetail.isNeedReversal) {
|
||||||
|
flag = true
|
||||||
|
batchUploadProcess()
|
||||||
|
} else {
|
||||||
|
flag = false
|
||||||
|
batchIndex = 0
|
||||||
|
|
||||||
|
updateDB()
|
||||||
|
insertPayDetail(currentPayDetail)
|
||||||
|
|
||||||
|
if (errorFlag) {
|
||||||
|
postStatus(TransactionStatus.ON_ERROR)
|
||||||
|
} else {
|
||||||
|
postStatus(TransactionStatus.ON_SUCCESS)
|
||||||
|
}
|
||||||
|
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(isLoading = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun batchUploadProcess() {
|
||||||
|
postStatus(TransactionStatus.ON_BATCH_UPLOAD)
|
||||||
|
|
||||||
|
val currentPayDetails = payDetails
|
||||||
|
|
||||||
|
if (currentPayDetails.isNullOrEmpty()) {
|
||||||
|
requestOnlineProcessSettlement()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val uploadPayDetail = currentPayDetails[batchIndex]
|
||||||
|
|
||||||
|
val tradeData = TradeData().apply {
|
||||||
|
payDetail = uploadPayDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
BatchUploadProcess.getInstance()
|
||||||
|
.enqueue(tradeData)
|
||||||
|
.startBatchUpload(object : BatchListener {
|
||||||
|
|
||||||
|
override fun onSuccessBatch() {
|
||||||
|
if (batchIndex < currentPayDetails.size - 1) {
|
||||||
|
LogUtil.d(TAG, "Pay detail size: ${currentPayDetails.size}")
|
||||||
|
LogUtil.d(TAG, "Count value: $batchIndex")
|
||||||
|
|
||||||
|
batchIndex++
|
||||||
|
batchUploadProcess()
|
||||||
|
} else {
|
||||||
|
requestOnlineProcessSettlement()
|
||||||
|
}
|
||||||
|
|
||||||
|
LogUtil.e(TAG, "Batch Upload Success")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailBatch() {
|
||||||
|
LogUtil.e(TAG, "Batch Upload Fail")
|
||||||
|
postStatus(TransactionStatus.ON_ERROR)
|
||||||
|
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(isLoading = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun postStatus(status: TransactionStatus) {
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(status = status)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModelScope.launch {
|
||||||
|
_events.send(SettlementEvent.ShowStatus(status))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -431,6 +431,10 @@ class SharedViewModel @Inject constructor(
|
|||||||
return repository.getLastThreeTransactions()
|
return repository.getLastThreeTransactions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSettlementRecords(): LiveData<List<PayDetail>> {
|
||||||
|
return repository.getSettlementPOS()
|
||||||
|
}
|
||||||
|
|
||||||
fun getReversalTransaction(voucherNo: String): LiveData<PayDetail> {
|
fun getReversalTransaction(voucherNo: String): LiveData<PayDetail> {
|
||||||
return repository.getReversalTransaction(voucherNo)
|
return repository.getReversalTransaction(voucherNo)
|
||||||
}
|
}
|
||||||
@ -445,6 +449,7 @@ class SharedViewModel @Inject constructor(
|
|||||||
|
|
||||||
fun saveMockHostResultForTesting() {
|
fun saveMockHostResultForTesting() {
|
||||||
when (transactionsType.value) {
|
when (transactionsType.value) {
|
||||||
|
TransactionsType.SETTLEMENT -> saveMockSettlementForTesting()
|
||||||
TransactionsType.VOID -> saveMockApprovedVoidForTesting()
|
TransactionsType.VOID -> saveMockApprovedVoidForTesting()
|
||||||
else -> saveMockApprovedSaleForVoidTesting()
|
else -> saveMockApprovedSaleForVoidTesting()
|
||||||
}
|
}
|
||||||
@ -553,6 +558,39 @@ class SharedViewModel @Inject constructor(
|
|||||||
approvalCode.value = mockApprovalCode
|
approvalCode.value = mockApprovalCode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun saveMockSettlementForTesting() {
|
||||||
|
val systemParams = SystemParamsOperation.getInstance()
|
||||||
|
val mockTraceNo = systemParams.incrementSerialNum
|
||||||
|
val mockInvoiceNo = systemParams.incrementInvoiceNum
|
||||||
|
|
||||||
|
val settlementDetail = PayDetail().apply {
|
||||||
|
merchantNo = systemParams.merchantId
|
||||||
|
merchantName = systemParams.merchantName
|
||||||
|
terminalNo = systemParams.terminalId
|
||||||
|
voucherNo = mockTraceNo
|
||||||
|
invoiceNo = mockInvoiceNo
|
||||||
|
batchNo = systemParams.systemParamsSettings.batchNumStart
|
||||||
|
processCode = TransactionsType.SETTLEMENT.processCode
|
||||||
|
transactionType = TransactionType.SETTLEMENT
|
||||||
|
transType = TransactionsType.SETTLEMENT.name
|
||||||
|
currencyCode = systemParams.currencyType.removed0CurrencyCode
|
||||||
|
tradeAnswerCode = "00"
|
||||||
|
tradeResultDes = "MOCK SETTLEMENT APPROVED"
|
||||||
|
TradeDate = SystemDateTime.getMMDD()
|
||||||
|
TradeTime = SystemDateTime.getHHmmss()
|
||||||
|
tradeDateAndTime = SystemDateTime.getMMDDhhmmss()
|
||||||
|
tradeDateTime = SystemDateTime.getYYMMDDhhmmss()
|
||||||
|
transDate = SystemDateTime.getTodayDateFormat()
|
||||||
|
transTime = SystemDateTime.getTodayTimeFormat()
|
||||||
|
isSettle = false
|
||||||
|
isNeedReversal = false
|
||||||
|
isCanceled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
payDetail.value = settlementDetail
|
||||||
|
traceNo.value = mockTraceNo
|
||||||
|
}
|
||||||
|
|
||||||
fun enableCardStatusIcon(
|
fun enableCardStatusIcon(
|
||||||
tapCard: Boolean,
|
tapCard: Boolean,
|
||||||
tapDevice: Boolean,
|
tapDevice: Boolean,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user