Uprość obsługę urlopów w aplikacji kierowcy

This commit is contained in:
admin
2026-07-30 00:24:39 +02:00
parent 062415a75d
commit 2e7eb7e47b
9 changed files with 1563 additions and 97 deletions
+1
View File
@@ -1,4 +1,5 @@
.gradle/ .gradle/
.kotlin/
build/ build/
local.properties local.properties
app/google-services.json app/google-services.json
@@ -2,6 +2,7 @@ package pl.firmatpp.kierowca.data
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.provider.OpenableColumns
import java.io.File import java.io.File
import java.security.MessageDigest import java.security.MessageDigest
import java.util.UUID import java.util.UUID
@@ -20,8 +21,12 @@ import pl.firmatpp.kierowca.data.model.DispatchSheetUploadResponse
import pl.firmatpp.kierowca.data.model.CreateLeaveRequestBody import pl.firmatpp.kierowca.data.model.CreateLeaveRequestBody
import pl.firmatpp.kierowca.data.model.DriverDto import pl.firmatpp.kierowca.data.model.DriverDto
import pl.firmatpp.kierowca.data.model.DriverLeaveCalendarEntryDto import pl.firmatpp.kierowca.data.model.DriverLeaveCalendarEntryDto
import pl.firmatpp.kierowca.data.model.DriverLeaveDocumentDto
import pl.firmatpp.kierowca.data.model.DriverLeaveForecastDto
import pl.firmatpp.kierowca.data.model.DriverLeaveRequestDto import pl.firmatpp.kierowca.data.model.DriverLeaveRequestDto
import pl.firmatpp.kierowca.data.model.DriverLeaveSummaryDto
import pl.firmatpp.kierowca.data.model.FinishRouteBody import pl.firmatpp.kierowca.data.model.FinishRouteBody
import pl.firmatpp.kierowca.data.model.LeaveForecastBody
import pl.firmatpp.kierowca.data.model.NotificationPreferencesBody import pl.firmatpp.kierowca.data.model.NotificationPreferencesBody
import pl.firmatpp.kierowca.data.model.NotificationPreferencesDto import pl.firmatpp.kierowca.data.model.NotificationPreferencesDto
import pl.firmatpp.kierowca.data.model.OtpResponse import pl.firmatpp.kierowca.data.model.OtpResponse
@@ -70,18 +75,92 @@ class DriverRepository(
suspend fun leaveRequests(): List<DriverLeaveRequestDto> = suspend fun leaveRequests(): List<DriverLeaveRequestDto> =
api.leaveRequests(authHeader(requireToken())).data api.leaveRequests(authHeader(requireToken())).data
suspend fun leaveSummary(): DriverLeaveSummaryDto =
api.leaveSummary(authHeader(requireToken())).data
suspend fun leaveForecast(
dateFrom: String,
dateTo: String,
type: String,
requestMode: String,
requestedQuantity: Int?,
): DriverLeaveForecastDto =
api.leaveForecast(
authHeader(requireToken()),
LeaveForecastBody(type, dateFrom, dateTo, requestMode, requestedQuantity),
).data
suspend fun leaveCalendar(from: String, to: String): List<DriverLeaveCalendarEntryDto> = suspend fun leaveCalendar(from: String, to: String): List<DriverLeaveCalendarEntryDto> =
api.leaveCalendar(authHeader(requireToken()), from, to).data api.leaveCalendar(authHeader(requireToken()), from, to).data
suspend fun leaveRequest(id: String): DriverLeaveRequestDto = suspend fun leaveRequest(id: String): DriverLeaveRequestDto =
api.leaveRequest(authHeader(requireToken()), id).data api.leaveRequest(authHeader(requireToken()), id).data
suspend fun createLeaveRequest(dateFrom: String, dateTo: String, type: String, note: String?): DriverLeaveRequestDto = suspend fun createLeaveRequest(
api.createLeaveRequest(authHeader(requireToken()), CreateLeaveRequestBody(dateFrom, dateTo, type, note)).data dateFrom: String,
dateTo: String,
type: String,
requestMode: String,
requestedQuantity: Int?,
details: Map<String, String>,
idempotencyKey: String,
note: String?,
): DriverLeaveRequestDto =
api.createLeaveRequest(
authHeader(requireToken()),
CreateLeaveRequestBody(
dateFrom = dateFrom,
dateTo = dateTo,
type = type,
requestMode = requestMode,
requestedQuantity = requestedQuantity,
details = details,
idempotencyKey = idempotencyKey,
note = note,
),
).data
suspend fun cancelLeaveRequest(id: String, expectedVersion: Long, comment: String? = null): DriverLeaveRequestDto = suspend fun cancelLeaveRequest(id: String, expectedVersion: Long, comment: String? = null): DriverLeaveRequestDto =
api.cancelLeaveRequest(authHeader(requireToken()), id, CancelLeaveRequestBody(comment, expectedVersion)).data api.cancelLeaveRequest(authHeader(requireToken()), id, CancelLeaveRequestBody(comment, expectedVersion)).data
suspend fun leaveDocuments(id: String): List<DriverLeaveDocumentDto> =
api.leaveDocuments(authHeader(requireToken()), id).data
suspend fun uploadLeaveDocument(id: String, documentType: String, uri: Uri): DriverLeaveDocumentDto {
val resolver = context.contentResolver
val mimeType = resolver.getType(uri) ?: "application/octet-stream"
val fileMetadata = resolver.query(
uri,
arrayOf(OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE),
null,
null,
null,
)?.use { cursor ->
if (!cursor.moveToFirst()) {
null
} else {
cursor.getString(0) to cursor.getLong(1)
}
}
if ((fileMetadata?.second ?: 0L) > 20L * 1024L * 1024L) {
error("Dokument jest za duży. Maksymalny rozmiar pliku to 20 MB.")
}
val bytes = resolver.openInputStream(uri)?.use { it.readBytes() }
?: error("Nie można odczytać wybranego dokumentu.")
val originalName = fileMetadata?.first
?.takeIf { it.isNotBlank() }
?: "dokument"
val body = bytes.toRequestBody(mimeType.toMediaTypeOrNull())
val file = MultipartBody.Part.createFormData("file", originalName, body)
return api.uploadLeaveDocument(
authHeader(requireToken()),
id,
file,
documentType.toPlainTextBody(),
).data
}
suspend fun completeRoute(routeId: String) = suspend fun completeRoute(routeId: String) =
api.completeRoute(authHeader(requireToken()), routeId) api.completeRoute(authHeader(requireToken()), routeId)
@@ -13,9 +13,14 @@ import pl.firmatpp.kierowca.data.model.CreateLeaveRequestBody
import pl.firmatpp.kierowca.data.model.DispatchSheetUploadResponse import pl.firmatpp.kierowca.data.model.DispatchSheetUploadResponse
import pl.firmatpp.kierowca.data.model.FinishRouteBody import pl.firmatpp.kierowca.data.model.FinishRouteBody
import pl.firmatpp.kierowca.data.model.LeaveCalendarResponse import pl.firmatpp.kierowca.data.model.LeaveCalendarResponse
import pl.firmatpp.kierowca.data.model.LeaveDocumentListResponse
import pl.firmatpp.kierowca.data.model.LeaveDocumentResponse
import pl.firmatpp.kierowca.data.model.LeaveForecastBody
import pl.firmatpp.kierowca.data.model.LeaveForecastResponse
import pl.firmatpp.kierowca.data.model.LeaveRequestListResponse import pl.firmatpp.kierowca.data.model.LeaveRequestListResponse
import pl.firmatpp.kierowca.data.model.LeaveRequestResponse import pl.firmatpp.kierowca.data.model.LeaveRequestResponse
import pl.firmatpp.kierowca.data.model.LeaveRequestTypesResponse import pl.firmatpp.kierowca.data.model.LeaveRequestTypesResponse
import pl.firmatpp.kierowca.data.model.LeaveSummaryResponse
import pl.firmatpp.kierowca.data.model.OtpResponse import pl.firmatpp.kierowca.data.model.OtpResponse
import pl.firmatpp.kierowca.data.model.NotificationPreferencesBody import pl.firmatpp.kierowca.data.model.NotificationPreferencesBody
import pl.firmatpp.kierowca.data.model.NotificationPreferencesDto import pl.firmatpp.kierowca.data.model.NotificationPreferencesDto
@@ -80,6 +85,17 @@ interface MobileDriverApi {
@Header("Authorization") authorization: String, @Header("Authorization") authorization: String,
): LeaveRequestTypesResponse ): LeaveRequestTypesResponse
@GET("mobile/driver/leave-summary")
suspend fun leaveSummary(
@Header("Authorization") authorization: String,
): LeaveSummaryResponse
@POST("mobile/driver/leave-forecast")
suspend fun leaveForecast(
@Header("Authorization") authorization: String,
@Body body: LeaveForecastBody,
): LeaveForecastResponse
@GET("mobile/driver/leave-requests") @GET("mobile/driver/leave-requests")
suspend fun leaveRequests( suspend fun leaveRequests(
@Header("Authorization") authorization: String, @Header("Authorization") authorization: String,
@@ -104,6 +120,21 @@ interface MobileDriverApi {
@Path("id") id: String, @Path("id") id: String,
): LeaveRequestResponse ): LeaveRequestResponse
@GET("mobile/driver/leave-requests/{id}/documents")
suspend fun leaveDocuments(
@Header("Authorization") authorization: String,
@Path("id") id: String,
): LeaveDocumentListResponse
@Multipart
@POST("mobile/driver/leave-requests/{id}/documents")
suspend fun uploadLeaveDocument(
@Header("Authorization") authorization: String,
@Path("id") id: String,
@Part file: MultipartBody.Part,
@Part("documentType") documentType: RequestBody,
): LeaveDocumentResponse
@POST("mobile/driver/leave-requests/{id}/cancel") @POST("mobile/driver/leave-requests/{id}/cancel")
suspend fun cancelLeaveRequest( suspend fun cancelLeaveRequest(
@Header("Authorization") authorization: String, @Header("Authorization") authorization: String,
@@ -223,13 +223,94 @@ data class LeaveRequestTypesResponse(
data class LeaveRequestTypeDto( data class LeaveRequestTypeDto(
val value: String, val value: String,
val code: String? = null,
val ruleCode: String? = null,
val label: String, val label: String,
val category: String? = null,
val unit: String? = null,
val poolCode: String? = null,
val requestModes: List<String> = listOf("days"),
val requiredFields: List<String> = emptyList(),
val requiredDocuments: List<String> = emptyList(),
val fieldOptions: Map<String, Map<String, String>> = emptyMap(),
val description: String? = null,
val decisionMode: String? = null,
val payrollMode: String? = null,
val legalBasis: String? = null,
)
data class LeaveSummaryResponse(
val data: DriverLeaveSummaryDto,
)
data class DriverLeaveSummaryDto(
val pools: List<DriverLeavePoolDto> = emptyList(),
val dailyNormMinutes: Int = 480,
val balanceConfigured: Boolean = false,
val overdueQuantity: Int = 0,
val availableTypes: List<LeaveRequestTypeDto> = emptyList(),
val reminders: List<DriverLeaveReminderDto> = emptyList(),
)
data class DriverLeavePoolDto(
val id: Int,
val poolCode: String,
val year: Int,
val unit: String,
val calculatedQuantity: Int = 0,
val confirmedQuantity: Int? = null,
val availableQuantity: Int = 0,
val reservedQuantity: Int = 0,
val usedQuantity: Int = 0,
val grantedQuantity: Int = 0,
val overdue: Boolean = false,
val status: String,
)
data class DriverLeaveReminderDto(
val code: String,
val message: String,
val poolId: Int? = null,
)
data class LeaveForecastBody(
val type: String,
val dateFrom: String,
val dateTo: String,
val requestMode: String,
val requestedQuantity: Int? = null,
)
data class LeaveForecastResponse(
val data: DriverLeaveForecastDto,
)
data class DriverLeaveForecastDto(
val ruleCode: String,
val quantityUnit: String,
val days: List<DriverLeaveForecastDayDto> = emptyList(),
val workingDaysCount: Int = 0,
val requestedQuantity: Int = 0,
val availableQuantity: Int = 0,
val balanceConfigured: Boolean = false,
val sufficientBalance: Boolean = true,
val pools: List<DriverLeavePoolDto> = emptyList(),
)
data class DriverLeaveForecastDayDto(
val date: String,
val quantity: Int,
val source: String? = null,
) )
data class CreateLeaveRequestBody( data class CreateLeaveRequestBody(
val dateFrom: String, val dateFrom: String,
val dateTo: String, val dateTo: String,
val type: String, val type: String,
val requestMode: String = "days",
val requestedQuantity: Int? = null,
val details: Map<String, String> = emptyMap(),
val idempotencyKey: String? = null,
val note: String?, val note: String?,
) )
@@ -244,7 +325,12 @@ data class DriverLeaveRequestDto(
val dateFrom: String?, val dateFrom: String?,
val dateTo: String?, val dateTo: String?,
val type: String, val type: String,
val ruleCode: String? = null,
val typeLabel: String? = null, val typeLabel: String? = null,
val requestMode: String = "days",
val requestedQuantity: Int? = null,
val rule: DriverLeaveRuleSnapshotDto? = null,
val details: Map<String, String> = emptyMap(),
val note: String? = null, val note: String? = null,
val status: String, val status: String,
val version: Long = 1, val version: Long = 1,
@@ -255,6 +341,54 @@ data class DriverLeaveRequestDto(
val decidedAt: String? = null, val decidedAt: String? = null,
val decisionComment: String? = null, val decisionComment: String? = null,
val events: List<DriverLeaveRequestEventDto> = emptyList(), val events: List<DriverLeaveRequestEventDto> = emptyList(),