new version 3.1.5 , fixed the bug where check out is showing after check in

This commit is contained in:
sathwikcs
2025-03-17 17:49:13 +05:30
parent b395df6268
commit f00774af08
3 changed files with 100 additions and 34 deletions

55
.idea/other.xml generated
View File

@@ -14,6 +14,17 @@
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1280" /> <option name="screenY" value="1280" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="OnePlus" />
<option name="codename" value="OP5552L1" />
<option name="id" value="OP5552L1" />
<option name="manufacturer" value="OnePlus" />
<option name="name" value="CPH2415" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2412" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="34" /> <option name="api" value="34" />
<option name="brand" value="OPPO" /> <option name="brand" value="OPPO" />
@@ -102,6 +113,17 @@
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="1272" /> <option name="screenY" value="1272" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="33" />
<option name="brand" value="motorola" />
<option name="codename" value="austin" />
<option name="id" value="austin" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g 5G (2022)" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="33" /> <option name="api" value="33" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
@@ -267,6 +289,17 @@
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gta9pwifi" />
<option name="id" value="gta9pwifi" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="SM-X210" />
<option name="screenDensity" value="240" />
<option name="screenX" value="1200" />
<option name="screenY" value="1920" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="34" /> <option name="api" value="34" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
@@ -300,6 +333,17 @@
<option name="screenX" value="1600" /> <option name="screenX" value="1600" />
<option name="screenY" value="2560" /> <option name="screenY" value="2560" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="gts9fe" />
<option name="id" value="gts9fe" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Tab S9 FE 5G" />
<option name="screenDensity" value="280" />
<option name="screenX" value="1440" />
<option name="screenY" value="2304" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="34" /> <option name="api" value="34" />
<option name="brand" value="google" /> <option name="brand" value="google" />
@@ -488,6 +532,17 @@
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2424" /> <option name="screenY" value="2424" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="35" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="id" value="tokay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
</list> </list>
</option> </option>
</component> </component>

View File

@@ -16,7 +16,7 @@ android {
targetSdk = 34 targetSdk = 34
versionCode = 11 versionCode = 11
versionName = "3.1.4" versionName = "3.1.5"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {

View File

@@ -14,11 +14,11 @@ import `in`.sminnovations.attendanceapp.utils.AppUpdater
import `in`.sminnovations.attendanceapp.utils.NetworkMonitor import `in`.sminnovations.attendanceapp.utils.NetworkMonitor
import `in`.sminnovations.attendanceapp.utils.UpdateChecker import `in`.sminnovations.attendanceapp.utils.UpdateChecker
import `in`.sminnovations.attendanceapp.utils.UpdateInfo import `in`.sminnovations.attendanceapp.utils.UpdateInfo
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.tasks.await
@@ -67,7 +67,6 @@ class HomeViewModel @Inject constructor(
} }
} }
// In your ViewModel, assume:
fun installUpdate(url: String) { fun installUpdate(url: String) {
@@ -106,20 +105,18 @@ class HomeViewModel @Inject constructor(
init { init {
networkMonitor.startMonitoring() networkMonitor.startMonitoring()
networkMonitor.isConnected.asFlow().onEach { isConnected -> viewModelScope.launch {
_uiState.update { currentState -> networkMonitor.isConnected.asFlow().collectLatest { isConnected ->
currentState.copy(isConnected = isConnected) _uiState.update { it.copy(isConnected = isConnected) }
} if (isConnected) {
}.launchIn(viewModelScope) startScanning()
if (uiState.value.isConnected) { }
viewModelScope.launch {
startScanning()
} }
} }
} }
fun reStartMonitoring() { fun reStartMonitoring() {
networkMonitor.startMonitoring() networkMonitor.startMonitoring()
} }
@@ -162,7 +159,6 @@ class HomeViewModel @Inject constructor(
private fun processQRCode(userId: String) { private fun processQRCode(userId: String) {
if (userId.isBlank()) return if (userId.isBlank()) return
viewModelScope.launch { viewModelScope.launch {
try { try {
setLoading(true) setLoading(true)
@@ -172,12 +168,13 @@ class HomeViewModel @Inject constructor(
// Fetch Employee Document // Fetch Employee Document
val employeeDoc = getEmployeeDocument(userId) val employeeDoc = getEmployeeDocument(userId)
delay(200L)
if (employeeDoc == null) { if (employeeDoc == null) {
handleError("Invalid employee ID") handleError("Invalid employee ID")
return@launch return@launch
} }
if (!employeeDoc.getBoolean("EmployeeStatus")!!) { if (employeeDoc.getBoolean("EmployeeStatus") != true) {
_uiState.update { _uiState.update {
it.copy( it.copy(
userName = employeeDoc.getString("Name"), userName = employeeDoc.getString("Name"),
@@ -195,10 +192,13 @@ class HomeViewModel @Inject constructor(
if (attendanceDoc?.exists() == true) { if (attendanceDoc?.exists() == true) {
handleExistingAttendance(attendanceDoc) handleExistingAttendance(attendanceDoc)
_uiState.update { it.copy(isCheckedOut = true, qrCodeValue = null) }
} else { } else {
handleNewAttendance(userId, currentDate) handleNewAttendance(userId, currentDate)
} }
} catch (e: Exception) { } catch (e: Exception) {
handleError("An error occurred: ${e.message}") handleError("An error occurred: ${e.message}")
} finally { } finally {
@@ -269,23 +269,35 @@ class HomeViewModel @Inject constructor(
val data = document.data ?: return val data = document.data ?: return
val checkIns = data.filterKeys { it.startsWith("checkIn") }.size val checkIns = data.filterKeys { it.startsWith("checkIn") }.size
val checkOuts = data.filterKeys { it.startsWith("checkOut") }.size val checkOuts = data.filterKeys { it.startsWith("checkOut") }.size
val checkIn = document.getString("checkIn$checkIns")!!
if (isTimeDifferenceGreaterThanSec(givenTimeStr = checkIn, currentTimeStr = formatTimestamp(Timestamp.now()), secVal = 5L)) { delay(200L)
if (!isTimeDifferenceGreaterThanMinutes(
givenTimeStr = checkIn, val currentTimestamp = formatTimestamp(Timestamp.now())
currentTimeStr = formatTimestamp(Timestamp.now()),
minutesVal = 5L val checkIn = document.getString("checkIn$checkIns") ?: run {
) handleError("Missing check-in data")
) { return
handleError("Wait 5 minutes before logging off") }
} else {
if (checkIns > checkOuts) {
processCheckOut(document, checkIns) if (isTimeDifferenceGreaterThanSec(givenTimeStr = checkIn, currentTimeStr = currentTimestamp, secVal = 5L)) {
} else { if (!isTimeDifferenceGreaterThanMinutes(givenTimeStr = checkIn, currentTimeStr = currentTimestamp, minutesVal = 5L)) {
processCheckIn(document, checkIns + 1) handleError("Wait 5 minutes before logging off")
} return
} } else {
} if (checkIns > checkOuts) {
processCheckOut(document, checkIns)
} else {
processCheckIn(document, checkIns + 1)
}
}
}else{
return
}
} }
@@ -342,8 +354,7 @@ class HomeViewModel @Inject constructor(
private suspend fun processCheckIn(document: DocumentSnapshot, checkInCount: Int) { private suspend fun processCheckIn(document: DocumentSnapshot, checkInCount: Int) {
try { try {
document.reference.update("checkIn$checkInCount", formatTimestamp(Timestamp.now())) document.reference.update("checkIn$checkInCount", formatTimestamp(Timestamp.now())).await()
.await()
_uiState.update { _uiState.update {
it.copy( it.copy(
isCheckedIn = true, qrCodeValue = null isCheckedIn = true, qrCodeValue = null