Compare commits

...
1 Commits
Author SHA1 Message Date
admin d6b36a1d3a Fix driver route crash on null photos 2026-07-08 00:02:15 +02:00
5 changed files with 44 additions and 3 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ android {
applicationId = "pl.firmatpp.kierowca" applicationId = "pl.firmatpp.kierowca"
minSdk = 26 minSdk = 26
targetSdk = 35 targetSdk = 35
versionCode = 49 versionCode = 50
versionName = "1.0.44" versionName = "1.0.44"
setProperty("archivesBaseName", "pl.firmatpp.kierowca") setProperty("archivesBaseName", "pl.firmatpp.kierowca")
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -1,6 +1,7 @@
package pl.firmatpp.kierowca.ui package pl.firmatpp.kierowca.ui
import pl.firmatpp.kierowca.data.model.DriverRouteDto import pl.firmatpp.kierowca.data.model.DriverRouteDto
import pl.firmatpp.kierowca.data.model.RoutePhotoDto
import pl.firmatpp.kierowca.data.upload.RouteActionEntity import pl.firmatpp.kierowca.data.upload.RouteActionEntity
import pl.firmatpp.kierowca.data.upload.RouteActionStatus import pl.firmatpp.kierowca.data.upload.RouteActionStatus
import pl.firmatpp.kierowca.data.upload.RouteActionType import pl.firmatpp.kierowca.data.upload.RouteActionType
@@ -41,6 +42,7 @@ fun projectDriverRoute(route: DriverRouteDto, actions: List<RouteActionEntity>):
status = "W TRAKCIE", status = "W TRAKCIE",
loadingWeight = action.weight, loadingWeight = action.weight,
trackingStatus = "active", trackingStatus = "active",
photos = projectedRoute.safePhotos(),
) )
loadingWeightPending = action.status != RouteActionStatus.Confirmed loadingWeightPending = action.status != RouteActionStatus.Confirmed
} }
@@ -50,6 +52,7 @@ fun projectDriverRoute(route: DriverRouteDto, actions: List<RouteActionEntity>):
unloadingWeight = action.weight, unloadingWeight = action.weight,
trackingStatus = "finished", trackingStatus = "finished",
completedAt = action.occurredAt, completedAt = action.occurredAt,
photos = projectedRoute.safePhotos(),
) )
unloadingWeightPending = action.status != RouteActionStatus.Confirmed unloadingWeightPending = action.status != RouteActionStatus.Confirmed
} }
@@ -71,3 +74,5 @@ fun projectDriverRoutes(routes: List<DriverRouteDto>, actions: List<RouteActionE
fun routeActionNeedsAttention(status: String): Boolean = fun routeActionNeedsAttention(status: String): Boolean =
status == RouteActionStatus.FailedConflict || status == RouteActionStatus.FailedPermanent status == RouteActionStatus.FailedConflict || status == RouteActionStatus.FailedPermanent
internal fun DriverRouteDto.safePhotos(): List<RoutePhotoDto> = photos.orEmpty()
@@ -151,9 +151,9 @@ fun routeFlowSteps(route: DriverRouteDto, actions: List<RouteActionEntity>): Lis
) )
} }
fun routePhotosForStage(photos: List<RoutePhotoDto>, stage: String): List<RoutePhotoDto> { fun routePhotosForStage(photos: List<RoutePhotoDto>?, stage: String): List<RoutePhotoDto> {
val normalized = normalizedRoutePhotoStage(stage) val normalized = normalizedRoutePhotoStage(stage)
return photos.filter { normalizedRoutePhotoStage(it.stage) == normalized } return photos.orEmpty().filter { normalizedRoutePhotoStage(it.stage) == normalized }
} }
fun normalizedRoutePhotoStage(stage: String?): String = fun normalizedRoutePhotoStage(stage: String?): String =
@@ -617,6 +617,7 @@ class DriverViewModel(application: Application) : AndroidViewModel(application)
status = "W TRAKCIE", status = "W TRAKCIE",
loadingWeight = weight, loadingWeight = weight,
trackingStatus = "active", trackingStatus = "active",
photos = route.safePhotos(),
) )
} }
"unloading" -> { "unloading" -> {
@@ -626,6 +627,7 @@ class DriverViewModel(application: Application) : AndroidViewModel(application)
unloadingWeight = weight, unloadingWeight = weight,
trackingStatus = "finished", trackingStatus = "finished",
completedAt = Instant.now().toString(), completedAt = Instant.now().toString(),
photos = route.safePhotos(),
) )
} }
else -> route else -> route
@@ -1,11 +1,13 @@
package pl.firmatpp.kierowca.ui package pl.firmatpp.kierowca.ui
import com.google.gson.Gson
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Test import org.junit.Test
import pl.firmatpp.kierowca.data.model.DriverRouteDto import pl.firmatpp.kierowca.data.model.DriverRouteDto
import pl.firmatpp.kierowca.data.model.RoutePhotoDto
import pl.firmatpp.kierowca.data.upload.RouteActionEntity import pl.firmatpp.kierowca.data.upload.RouteActionEntity
import pl.firmatpp.kierowca.data.upload.RouteActionStatus import pl.firmatpp.kierowca.data.upload.RouteActionStatus
import pl.firmatpp.kierowca.data.upload.RouteActionType import pl.firmatpp.kierowca.data.upload.RouteActionType
@@ -73,6 +75,38 @@ class DriverRouteProjectionTest {
assertEquals(emptyList<RouteActionEntity>(), projection.visibleActions) assertEquals(emptyList<RouteActionEntity>(), projection.visibleActions)
} }
@Test
fun routeProjectionNormalizesNullPhotosFromCachedJsonBeforeCopy() {
val route = Gson().fromJson(
"""
{
"id": "1",
"startsAt": "",
"originName": "Baza",
"destinationName": "Instalacja",
"contractorName": "TPP",
"contractName": "Kontrakt",
"contractCode": "TPP-1",
"relationLabel": "Baza -> Instalacja",
"status": "ZAPLANOWANA",
"distanceKm": 1.0,
"notes": null,
"truck": null,
"photos": null
}
""".trimIndent(),
DriverRouteDto::class.java,
)
val projection = projectDriverRoute(
route = route,
actions = listOf(action(RouteActionType.Start, RouteActionStatus.Confirmed, weight = 12.5)),
)
assertEquals("W TRAKCIE", projection.route.status)
assertEquals(emptyList<RoutePhotoDto>(), projection.route.photos)
}
@Test @Test
fun conflictKeepsLocalRouteValuesAndMarksStageAsAttention() { fun conflictKeepsLocalRouteValuesAndMarksStageAsAttention() {
val projection = projectDriverRoute( val projection = projectDriverRoute(