Przeliczaj wagi kierowcy z kilogramów na tony
This commit is contained in:
@@ -2746,16 +2746,14 @@ private fun RouteStageScreen(
|
||||
label = { Text(weightLabel) },
|
||||
trailingIcon = {
|
||||
Text(
|
||||
"t",
|
||||
"t / kg",
|
||||
color = TppTheme.colors.muted,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
},
|
||||
supportingText = {
|
||||
if (weightBlocker != null) {
|
||||
Text(weightBlocker)
|
||||
}
|
||||
Text(weightBlocker ?: routeWeightInputHelpText(state.routeStageWeightText))
|
||||
},
|
||||
isError = weightBlocker != null,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package pl.firmatpp.kierowca.ui
|
||||
|
||||
import java.io.File
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.Locale
|
||||
import kotlin.math.abs
|
||||
import pl.firmatpp.kierowca.data.model.DriverRouteDto
|
||||
import pl.firmatpp.kierowca.data.model.DispatchSheetReminderDto
|
||||
import pl.firmatpp.kierowca.data.model.RoutePhotoDto
|
||||
@@ -15,6 +19,8 @@ import pl.firmatpp.kierowca.data.upload.RouteActionStatus
|
||||
import pl.firmatpp.kierowca.data.upload.RouteActionType
|
||||
|
||||
private val shortDateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM")
|
||||
private val routeWeightKilogramInputThreshold = BigDecimal("1000")
|
||||
private const val routeWeightMaxTons = 999.999
|
||||
|
||||
enum class RouteFlowStepState {
|
||||
Todo,
|
||||
@@ -150,6 +156,31 @@ fun routeStageRequirementIsVisible(requirement: String): Boolean =
|
||||
fun routeStageRequirementIsRequired(requirement: String): Boolean =
|
||||
normalizeRouteStageRequirement(requirement) == RouteStageRequirement.Required
|
||||
|
||||
fun parseRouteWeightTons(weightText: String): Double? {
|
||||
val enteredWeight = weightText.trim().replace(',', '.').toBigDecimalOrNull() ?: return null
|
||||
val tons = if (enteredWeight.abs() >= routeWeightKilogramInputThreshold) {
|
||||
enteredWeight.movePointLeft(3)
|
||||
} else {
|
||||
enteredWeight
|
||||
}
|
||||
|
||||
return tons.setScale(3, RoundingMode.HALF_UP).toDouble()
|
||||
}
|
||||
|
||||
fun routeWeightInputHelpText(weightText: String): String {
|
||||
val enteredWeight = weightText.trim().replace(',', '.').toDoubleOrNull()
|
||||
val tons = parseRouteWeightTons(weightText)
|
||||
val enteredAsKilograms = enteredWeight != null &&
|
||||
abs(enteredWeight) >= routeWeightKilogramInputThreshold.toDouble() &&
|
||||
tons != null
|
||||
|
||||
return if (enteredAsKilograms) {
|
||||
"Wpisano kilogramy — zapiszemy ${String.format(Locale("pl", "PL"), "%.3f", tons)} t."
|
||||
} else {
|
||||
"Wpisz tony (np. 23,4). Wartości od 1000 rozpoznajemy jako kilogramy (np. 23400)."
|
||||
}
|
||||
}
|
||||
|
||||
fun canSubmitRouteStageForm(
|
||||
weightText: String,
|
||||
serverPhotoCount: Int,
|
||||
@@ -188,13 +219,14 @@ fun loadingWeightSubmitBlocker(
|
||||
photoRequirement: String = RouteStageRequirement.Required,
|
||||
): String? {
|
||||
val trimmed = weightText.trim()
|
||||
val normalizedWeight = trimmed.replace(',', '.').toDoubleOrNull()
|
||||
val normalizedWeight = parseRouteWeightTons(trimmed)
|
||||
val weightVisible = routeStageRequirementIsVisible(weightRequirement)
|
||||
|
||||
return when {
|
||||
weightVisible && routeStageRequirementIsRequired(weightRequirement) && trimmed.isBlank() -> "Podaj tonaż."
|
||||
weightVisible && trimmed.isNotBlank() && normalizedWeight == null -> "Podaj poprawny tonaż."
|
||||
weightVisible && normalizedWeight != null && normalizedWeight <= 0.0 -> "Tonaż musi być większy od zera."
|
||||
weightVisible && normalizedWeight != null && normalizedWeight > routeWeightMaxTons -> "Tonaż nie może przekraczać 999,999 t."
|
||||
loadingPhotosSubmitBlocker(serverPhotoCount, localUploadCount, photoRequirement) != null -> "Dodaj co najmniej jedno zdjęcie załadunku."
|
||||
else -> null
|
||||
}
|
||||
@@ -208,13 +240,14 @@ fun routeStageSubmitBlocker(
|
||||
photoRequirement: String = RouteStageRequirement.Required,
|
||||
): String? {
|
||||
val trimmed = weightText.trim()
|
||||
val normalizedWeight = trimmed.replace(',', '.').toDoubleOrNull()
|
||||
val normalizedWeight = parseRouteWeightTons(trimmed)
|
||||
val weightVisible = routeStageRequirementIsVisible(weightRequirement)
|
||||
|
||||
return when {
|
||||
weightVisible && routeStageRequirementIsRequired(weightRequirement) && trimmed.isBlank() -> "Podaj tonaż."
|
||||
weightVisible && trimmed.isNotBlank() && normalizedWeight == null -> "Podaj poprawny tonaż."
|
||||
weightVisible && normalizedWeight != null && normalizedWeight <= 0.0 -> "Tonaż musi być większy od zera."
|
||||
weightVisible && normalizedWeight != null && normalizedWeight > routeWeightMaxTons -> "Tonaż nie może przekraczać 999,999 t."
|
||||
routeStageRequirementIsRequired(photoRequirement) && visiblePhotoAttachmentCount(serverPhotoCount, localUploadCount) <= 0 -> "Dodaj co najmniej jedno zdjęcie etapu."
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -1103,7 +1103,7 @@ class DriverViewModel(application: Application) : AndroidViewModel(application)
|
||||
val photoRequirement = if (stage == "loading") snapshot.loadingPhotoRequirement else snapshot.unloadingPhotoRequirement
|
||||
val weightRequirement = if (stage == "loading") snapshot.loadingWeightRequirement else snapshot.unloadingWeightRequirement
|
||||
val weight = if (routeStageRequirementIsVisible(weightRequirement)) {
|
||||
snapshot.routeStageWeightText.trim().replace(',', '.').toDoubleOrNull()
|
||||
parseRouteWeightTons(snapshot.routeStageWeightText)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -306,11 +306,20 @@ class DriverUiRulesTest {
|
||||
fun routeStageFormRequiresPositiveWeightAndAtLeastOnePhotoOrQueuedUpload() {
|
||||
assertTrue(canSubmitRouteStageForm(weightText = "12,5", serverPhotoCount = 1, localUploadCount = 0))
|
||||
assertTrue(canSubmitRouteStageForm(weightText = "12.5", serverPhotoCount = 0, localUploadCount = 1))
|
||||
assertTrue(canSubmitRouteStageForm(weightText = "23400", serverPhotoCount = 1, localUploadCount = 0))
|
||||
assertFalse(canSubmitRouteStageForm(weightText = "", serverPhotoCount = 1, localUploadCount = 0))
|
||||
assertFalse(canSubmitRouteStageForm(weightText = "0", serverPhotoCount = 1, localUploadCount = 0))
|
||||
assertFalse(canSubmitRouteStageForm(weightText = "12.5", serverPhotoCount = 0, localUploadCount = 0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesRouteWeightsEnteredInTonsOrKilograms() {
|
||||
assertEquals(23.4, parseRouteWeightTons("23,4") ?: 0.0, 0.0)
|
||||
assertEquals(23.4, parseRouteWeightTons("23400") ?: 0.0, 0.0)
|
||||
assertEquals(23.401, parseRouteWeightTons("23400,5") ?: 0.0, 0.0)
|
||||
assertEquals("Wpisano kilogramy — zapiszemy 23,400 t.", routeWeightInputHelpText("23400"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun filtersRoutePhotosByStageWithOtherFallback() {
|
||||
val photos = listOf(
|
||||
|
||||
Reference in New Issue
Block a user