feat(tours): GET /me/tours mit optionalem ?date= (statt /me/tours/today)
Fahrer können jetzt die Tour eines beliebigen Datums abrufen (z. B. morgen vorab). Ohne date-Param bleibt serverseitig 'heute' (Local::now bzw. Dev-today_override); Praezedenz: requested_date > today_override > Uhr. Endpoint umbenannt /me/tours/today -> /me/tours (semantisch sauberer). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -1,11 +1,13 @@
|
||||
use axum::Json;
|
||||
use axum::Router;
|
||||
use axum::extract::{Path, State};
|
||||
use axum::extract::{Path, Query, State};
|
||||
use axum::routing::{get, post, put};
|
||||
use chrono::NaiveDate;
|
||||
use holzleitner_application::dto::{
|
||||
SetDeliveryOrderRequest, SetDeliveryOrderResponse, SyncTourRequest, TourDetails, TourSummary,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use holzleitner_application::error::ApplicationError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::error::ApiError;
|
||||
@ -14,7 +16,7 @@ use crate::state::AppState;
|
||||
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/me/tours/today", get(list_my_tours_today))
|
||||
.route("/me/tours", get(list_my_tours))
|
||||
.route("/tours/{tour_id}", get(get_tour))
|
||||
.route("/tours/{tour_id}/delivery-order", put(set_delivery_order))
|
||||
.route("/sync/tour", post(sync_tour))
|
||||
@ -37,27 +39,52 @@ pub struct SyncTourResponse {
|
||||
pub tour_id: Uuid,
|
||||
}
|
||||
|
||||
/// Listet heutige Touren des angemeldeten Fahrers (Filter aus dem JWT).
|
||||
/// Query für `GET /me/tours`. Optionales Ziel-Datum; fehlt es, gilt
|
||||
/// serverseitig „heute" (siehe `ListMyToursTodayUseCase`).
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ListToursQuery {
|
||||
/// Ziel-Tourdatum `YYYY-MM-DD`. Fehlt der Parameter, wird **heute**
|
||||
/// (Serverzeit bzw. Dev-Override) verwendet.
|
||||
#[serde(default)]
|
||||
pub date: Option<String>,
|
||||
}
|
||||
|
||||
/// Listet die Touren des angemeldeten Fahrers (Filter aus dem JWT) für ein
|
||||
/// Ziel-Datum. Ohne `?date=` gilt „heute". Der Fahrer wählt das Datum aktiv
|
||||
/// im Kopf-Kalender der App (z. B. um die Tour von morgen vorab zu sehen).
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/me/tours/today",
|
||||
path = "/me/tours",
|
||||
tag = "tours",
|
||||
params(
|
||||
("date" = Option<String>, Query, description = "Ziel-Tourdatum YYYY-MM-DD (Default: heute)")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Liste der heutigen Touren", body = TourSummaryList),
|
||||
(status = 200, description = "Liste der Touren am Ziel-Datum", body = TourSummaryList),
|
||||
(status = 400, description = "Ungültiges Datum"),
|
||||
(status = 401, description = "Authentifizierung fehlgeschlagen")
|
||||
),
|
||||
security(
|
||||
("bearer_auth" = [])
|
||||
)
|
||||
)]
|
||||
pub async fn list_my_tours_today(
|
||||
pub async fn list_my_tours(
|
||||
State(state): State<AppState>,
|
||||
AuthenticatedUser(claims): AuthenticatedUser,
|
||||
Query(query): Query<ListToursQuery>,
|
||||
) -> Result<Json<TourSummaryList>, ApiError> {
|
||||
tracing::debug!(personalnummer = claims.personalnummer, "list_my_tours_today");
|
||||
let date = match query.date {
|
||||
Some(s) => Some(NaiveDate::parse_from_str(s.trim(), "%Y-%m-%d").map_err(|e| {
|
||||
ApiError(ApplicationError::Validation(format!(
|
||||
"ungültiges Datum '{s}' (erwartet YYYY-MM-DD): {e}"
|
||||
)))
|
||||
})?),
|
||||
None => None,
|
||||
};
|
||||
tracing::debug!(personalnummer = claims.personalnummer, ?date, "list_my_tours");
|
||||
let tours = state
|
||||
.list_my_tours_today
|
||||
.execute(claims.personalnummer)
|
||||
.execute(claims.personalnummer, date)
|
||||
.await?;
|
||||
Ok(Json(TourSummaryList { tours }))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user