94 lines
2.9 KiB
Rust
94 lines
2.9 KiB
Rust
//! Reservations, from the administration side.
|
|
//!
|
|
//! Reading the whole list is an admin action for now; changing a status is
|
|
//! reserved to the unit the reservation belongs to (an admin manages every
|
|
//! unit), which is why the handler resolves the unit before narrowing the
|
|
//! controller down.
|
|
|
|
use aide::{
|
|
axum::{ApiRouter, routing::get_with},
|
|
transform::TransformOperation,
|
|
};
|
|
use axum::{
|
|
Json,
|
|
extract::Path,
|
|
http::StatusCode,
|
|
};
|
|
use schemars::JsonSchema;
|
|
use serde::Deserialize;
|
|
|
|
use crate::{
|
|
api::helpers::{admin, admin_desc, manager, manager_desc, unexpected_error},
|
|
core::{
|
|
controller::{AppController, ControllerError, reservations::ReservationsControllerError},
|
|
models::reservation::{Reservation, ReservationId, ReservationStatus},
|
|
},
|
|
};
|
|
|
|
pub fn routes() -> ApiRouter {
|
|
ApiRouter::new()
|
|
.api_route("/", get_with(get_reservations, get_reservations_docs))
|
|
.api_route(
|
|
"/{id}/status",
|
|
aide::axum::routing::put_with(set_status, set_status_docs),
|
|
)
|
|
}
|
|
|
|
#[axum::debug_handler]
|
|
async fn get_reservations(
|
|
ac: AppController,
|
|
) -> Result<Json<Vec<Reservation>>, (StatusCode, String)> {
|
|
match admin(ac)?.get_reservations().await {
|
|
Ok(reservations) => Ok(Json(reservations)),
|
|
Err(err) => unexpected_error("get_reservations", err),
|
|
}
|
|
}
|
|
|
|
fn get_reservations_docs(op: TransformOperation) -> TransformOperation {
|
|
op.tag("Reservations")
|
|
.summary("Get every reservation")
|
|
.response_with::<403, (), _>(admin_desc)
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, JsonSchema)]
|
|
struct SetStatusForm {
|
|
status: ReservationStatus,
|
|
}
|
|
|
|
#[axum::debug_handler]
|
|
async fn set_status(
|
|
ac: AppController,
|
|
Path(id): Path<ReservationId>,
|
|
Json(SetStatusForm { status }): Json<SetStatusForm>,
|
|
) -> Result<(), (StatusCode, String)> {
|
|
// The unit is not in the body: it is the reservation's own
|
|
let reservation = match ac.get_reservation(id).await {
|
|
Ok(reservation) => reservation,
|
|
Err(err) if err.is_not_found() => {
|
|
return Err((StatusCode::NOT_FOUND, "No such reservation".to_owned()));
|
|
}
|
|
Err(err) => return unexpected_error("set_status", err),
|
|
};
|
|
|
|
match manager(ac, reservation.unit.id)?
|
|
.set_reservation_status(id, status)
|
|
.await
|
|
{
|
|
Ok(()) => Ok(()),
|
|
Err(ControllerError::Reservation(err @ ReservationsControllerError::InvalidTransition(..))) => {
|
|
Err((StatusCode::CONFLICT, err.to_string()))
|
|
}
|
|
Err(err) => unexpected_error("set_status", err),
|
|
}
|
|
}
|
|
|
|
fn set_status_docs(op: TransformOperation) -> TransformOperation {
|
|
op.tag("Reservations")
|
|
.summary("Move a reservation through its state machine")
|
|
.description(
|
|
"Refuses a transition the state machine does not allow, with a 409.",
|
|
)
|
|
.response_with::<403, (), _>(manager_desc)
|
|
.response::<404, ()>()
|
|
.response::<409, ()>()
|
|
}
|