feat: Add excludeFromBilling option for diary dates and update related functionality
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s
This commit is contained in:
@@ -1588,6 +1588,7 @@ private fun DiaryListScreen(
|
||||
var newDiaryDateStr by rememberSaveable { mutableStateOf("") }
|
||||
var newDiaryStart by rememberSaveable { mutableStateOf("") }
|
||||
var newDiaryEnd by rememberSaveable { mutableStateOf("") }
|
||||
var newDiaryExcludeFromBilling by rememberSaveable { mutableStateOf(false) }
|
||||
val newDateScope = rememberCoroutineScope()
|
||||
var newDateScheduleGroups by remember { mutableStateOf<List<TrainingGroupDto>>(emptyList()) }
|
||||
var newDateScheduleLoading by remember { mutableStateOf(false) }
|
||||
@@ -1735,6 +1736,7 @@ private fun DiaryListScreen(
|
||||
newDiaryDateStr = kotlin.runCatching { java.time.LocalDate.now().toString() }.getOrElse { "" }
|
||||
newDiaryStart = diaryTimeForFormField(tmpl?.trainingStart).ifBlank { "17:30" }
|
||||
newDiaryEnd = diaryTimeForFormField(tmpl?.trainingEnd).ifBlank { "19:30" }
|
||||
newDiaryExcludeFromBilling = false
|
||||
showNewDateDialog = true
|
||||
},
|
||||
modifier = Modifier.heightIn(min = TouchMinHeight),
|
||||
@@ -1774,6 +1776,7 @@ private fun DiaryListScreen(
|
||||
slot.date,
|
||||
diaryTimeFieldToApi(slot.trainingStart),
|
||||
diaryTimeFieldToApi(slot.trainingEnd),
|
||||
excludeFromBilling = false,
|
||||
)
|
||||
quickCreateBusy = false
|
||||
if (id != null) {
|
||||
@@ -1922,6 +1925,20 @@ private fun DiaryListScreen(
|
||||
enabled = !diaryState.isLoading,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Text("Nicht abrechnen")
|
||||
Switch(
|
||||
checked = newDiaryExcludeFromBilling,
|
||||
onCheckedChange = { newDiaryExcludeFromBilling = it },
|
||||
enabled = !diaryState.isLoading,
|
||||
)
|
||||
}
|
||||
diaryState.error?.let { err ->
|
||||
Text(
|
||||
err,
|
||||
@@ -1941,6 +1958,7 @@ private fun DiaryListScreen(
|
||||
newDiaryDateStr.trim(),
|
||||
diaryTimeFieldToApi(newDiaryStart),
|
||||
diaryTimeFieldToApi(newDiaryEnd),
|
||||
newDiaryExcludeFromBilling,
|
||||
)
|
||||
if (id != null) {
|
||||
showNewDateDialog = false
|
||||
@@ -2775,10 +2793,11 @@ private fun DiaryDetailScreen(
|
||||
initialDate = entry.date.take(10),
|
||||
initialStart = entry.trainingStart.orEmpty(),
|
||||
initialEnd = entry.trainingEnd.orEmpty(),
|
||||
initialExcludeFromBilling = entry.excludeFromBilling,
|
||||
submitLabel = tr("common.save", "Speichern"),
|
||||
onSubmit = { _, start, end ->
|
||||
onSubmit = { _, start, end, excludeFromBilling ->
|
||||
dependencies.applicationScope.launch {
|
||||
dependencies.diaryManager.updateTimes(clubId, entry.id, start, end)
|
||||
dependencies.diaryManager.updateTimes(clubId, entry.id, start, end, excludeFromBilling)
|
||||
showEdit = false
|
||||
}
|
||||
},
|
||||
@@ -6878,14 +6897,16 @@ private fun DeleteAccountDialog(
|
||||
@Composable
|
||||
private fun DiaryEditForm(
|
||||
submitLabel: String,
|
||||
onSubmit: (date: String, trainingStart: String?, trainingEnd: String?) -> Unit,
|
||||
onSubmit: (date: String, trainingStart: String?, trainingEnd: String?, excludeFromBilling: Boolean) -> Unit,
|
||||
initialDate: String = "",
|
||||
initialStart: String = "",
|
||||
initialEnd: String = "",
|
||||
initialExcludeFromBilling: Boolean = false,
|
||||
) {
|
||||
var date by rememberSaveable { mutableStateOf(initialDate) }
|
||||
var start by rememberSaveable { mutableStateOf(initialStart) }
|
||||
var end by rememberSaveable { mutableStateOf(initialEnd) }
|
||||
var excludeFromBilling by rememberSaveable { mutableStateOf(initialExcludeFromBilling) }
|
||||
var error by rememberSaveable { mutableStateOf<String?>(null) }
|
||||
|
||||
Card(modifier = Modifier.fillMaxWidth().padding(vertical = 12.dp), elevation = 2.dp) {
|
||||
@@ -6895,6 +6916,17 @@ private fun DiaryEditForm(
|
||||
OutlinedTextField(value = start, onValueChange = { start = it }, label = { Text("Start") }, modifier = Modifier.weight(1f), singleLine = true)
|
||||
OutlinedTextField(value = end, onValueChange = { end = it }, label = { Text("Ende") }, modifier = Modifier.weight(1f), singleLine = true)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Text("Nicht abrechnen")
|
||||
Switch(
|
||||
checked = excludeFromBilling,
|
||||
onCheckedChange = { excludeFromBilling = it },
|
||||
)
|
||||
}
|
||||
ErrorText(error)
|
||||
Button(onClick = {
|
||||
if (!date.matches(Regex("\\d{4}-\\d{2}-\\d{2}"))) {
|
||||
@@ -6906,7 +6938,7 @@ private fun DiaryEditForm(
|
||||
return@Button
|
||||
}
|
||||
error = null
|
||||
onSubmit(date, start.takeIf { it.isNotBlank() }, end.takeIf { it.isNotBlank() })
|
||||
onSubmit(date, start.takeIf { it.isNotBlank() }, end.takeIf { it.isNotBlank() }, excludeFromBilling)
|
||||
}) {
|
||||
Text(submitLabel)
|
||||
}
|
||||
|
||||
@@ -197,6 +197,65 @@ private fun GlobalOrdersScreen(dependencies: AppDependencies, onBack: () -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
fun quickSaveFlags(orderId: Int, nextStatus: String? = null, nextPaidConfirmed: Boolean? = null) {
|
||||
val snapshot = rows.firstOrNull { it.order.id == orderId } ?: return
|
||||
val patchedStatus = nextStatus ?: snapshot.draftStatus
|
||||
val patchedPaidConfirmed = nextPaidConfirmed ?: snapshot.draftPaidConfirmed
|
||||
val memberId = snapshot.order.memberId ?: return
|
||||
val orderClubId = snapshot.order.clubId ?: return
|
||||
|
||||
rows = rows.map {
|
||||
if (it.order.id == orderId) {
|
||||
it.copy(
|
||||
draftStatus = patchedStatus,
|
||||
draftPaidConfirmed = patchedPaidConfirmed,
|
||||
)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
savingIds = savingIds + orderId
|
||||
runCatching {
|
||||
dependencies.memberOrdersApi.update(
|
||||
clubId = orderClubId,
|
||||
memberId = memberId,
|
||||
orderId = orderId,
|
||||
body = MemberOrderPatchBody(
|
||||
// Nur Status-Flags sofort speichern; restliche Felder bleiben Draft bis "Speichern".
|
||||
item = snapshot.order.item,
|
||||
status = patchedStatus,
|
||||
cost = normalizeAmount(snapshot.order.cost),
|
||||
paidAmount = normalizeAmount(snapshot.order.paidAmount),
|
||||
budget = normalizeAmount(snapshot.order.budget),
|
||||
paidConfirmed = patchedPaidConfirmed,
|
||||
),
|
||||
).order
|
||||
}.onSuccess { updated ->
|
||||
if (updated != null) {
|
||||
rows = rows.map { row ->
|
||||
if (row.order.id == orderId) {
|
||||
row.copy(
|
||||
order = updated,
|
||||
draftStatus = updated.status,
|
||||
draftPaidConfirmed = updated.paidConfirmed,
|
||||
)
|
||||
} else {
|
||||
row
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onFailure { e ->
|
||||
rows = rows.map {
|
||||
if (it.order.id == orderId) snapshot else it
|
||||
}
|
||||
err = e.message
|
||||
}
|
||||
savingIds = savingIds - orderId
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@@ -338,8 +397,9 @@ private fun GlobalOrdersScreen(dependencies: AppDependencies, onBack: () -> Unit
|
||||
orderStatuses.forEach { (v, k) ->
|
||||
TextButton(
|
||||
onClick = {
|
||||
rows = rows.map { if (it.order.id == o.id) it.copy(draftStatus = v) else it }
|
||||
quickSaveFlags(orderId = o.id, nextStatus = v)
|
||||
},
|
||||
enabled = !savingIds.contains(o.id),
|
||||
) {
|
||||
Text(
|
||||
tr(k, v),
|
||||
@@ -373,8 +433,9 @@ private fun GlobalOrdersScreen(dependencies: AppDependencies, onBack: () -> Unit
|
||||
Switch(
|
||||
checked = row.draftPaidConfirmed,
|
||||
onCheckedChange = { v ->
|
||||
rows = rows.map { if (it.order.id == o.id) it.copy(draftPaidConfirmed = v) else it }
|
||||
quickSaveFlags(orderId = o.id, nextPaidConfirmed = v)
|
||||
},
|
||||
enabled = !savingIds.contains(o.id),
|
||||
)
|
||||
Text(tr("orders.paidConfirmed", "Bezahlt bestätigt"), modifier = Modifier.padding(start = 8.dp))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user