Add an accommodations reservations module #188
@ -2,8 +2,69 @@ use crate::controllers::HttpResult;
|
||||
use crate::extractors::accommodation_extractor::FamilyAndAccommodationInPath;
|
||||
use crate::extractors::accommodation_reservation_extractor::FamilyAndAccommodationReservationInPath;
|
||||
use crate::extractors::family_extractor::FamilyInPath;
|
||||
use crate::models::NewAccommodationReservation;
|
||||
use crate::services::accommodations_reservations_service;
|
||||
use actix_web::HttpResponse;
|
||||
use crate::utils::time_utils::time;
|
||||
use actix_web::{web, HttpResponse};
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct CreateReservationQuery {
|
||||
start: usize,
|
||||
end: usize,
|
||||
}
|
||||
|
||||
/// Create a reservation
|
||||
pub async fn create_reservation(
|
||||
a: FamilyAndAccommodationInPath,
|
||||
req: web::Json<CreateReservationQuery>,
|
||||
) -> HttpResult {
|
||||
if !a.open_to_reservations {
|
||||
return Ok(HttpResponse::ExpectationFailed()
|
||||
.json("The accommodation is not open to reservations!"));
|
||||
}
|
||||
|
||||
if (req.start as i64) < (time() as i64 - 3600 * 24 * 30) {
|
||||
return Ok(HttpResponse::BadRequest().json("Start time is too far in the past!"));
|
||||
}
|
||||
|
||||
if req.start > req.end {
|
||||
return Ok(HttpResponse::BadRequest().json("End time happens before start time!"));
|
||||
}
|
||||
|
||||
let existing = accommodations_reservations_service::get_reservations_for_time_interval(
|
||||
a.id(),
|
||||
req.start,
|
||||
req.end,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if existing.iter().any(|r| r.validated != Some(false)) {
|
||||
return Ok(
|
||||
HttpResponse::Conflict().json("This reservation is in conflict with another one!")
|
||||
);
|
||||
}
|
||||
|
||||
let mut reservation =
|
||||
accommodations_reservations_service::create(&NewAccommodationReservation {
|
||||
family_id: a.family_id().0,
|
||||
accommodation_id: a.id().0,
|
||||
user_id: a.membership().user_id().0,
|
||||
time_create: time() as i64,
|
||||
time_update: time() as i64,
|
||||
reservation_start: req.start as i64,
|
||||
reservation_end: req.end as i64,
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Auto validate reservation if requested
|
||||
if !a.need_validation {
|
||||
reservation.validated = Some(true);
|
||||
|
||||
accommodations_reservations_service::update(&mut reservation).await?;
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok().json(reservation))
|
||||
}
|
||||
|
||||
/// Get the reservations for a given accommodation
|
||||
pub async fn get_accommodation_reservations(a: FamilyAndAccommodationInPath) -> HttpResult {
|
||||
|
@ -236,7 +236,10 @@ async fn main() -> std::io::Result<()> {
|
||||
"/family/{id}/accommodations/reservations/full_list",
|
||||
web::get().to(accommodations_reservations_controller::full_list),
|
||||
)
|
||||
// TODO : create
|
||||
.route(
|
||||
"/family/{id}/accommodations/reservations/accommodation/{accommodation_id}/create",
|
||||
web::post().to(accommodations_reservations_controller::create_reservation),
|
||||
)
|
||||
.route(
|
||||
"/family/{id}/accommodations/reservation/{reservation_id}",
|
||||
web::get().to(accommodations_reservations_controller::get_single),
|
||||
|
@ -1,10 +1,42 @@
|
||||
use crate::connections::db_connection;
|
||||
use crate::models::{
|
||||
AccommodationID, AccommodationReservation, AccommodationReservationID, FamilyID,
|
||||
NewAccommodationReservation,
|
||||
};
|
||||
use crate::schema::accommodations_reservations;
|
||||
use crate::utils::time_utils::time;
|
||||
use diesel::prelude::*;
|
||||
|
||||
/// Create a new reservation
|
||||
pub async fn create(new: &NewAccommodationReservation) -> anyhow::Result<AccommodationReservation> {
|
||||
db_connection::execute(|conn| {
|
||||
let res: AccommodationReservation = diesel::insert_into(accommodations_reservations::table)
|
||||
.values(new)
|
||||
.get_result(conn)?;
|
||||
|
||||
Ok(res)
|
||||
})
|
||||
}
|
||||
|
||||
/// Update a reservation
|
||||
pub async fn update(r: &mut AccommodationReservation) -> anyhow::Result<()> {
|
||||
r.time_update = time() as i64;
|
||||
|
||||
db_connection::execute(|conn| {
|
||||
diesel::update(
|
||||
accommodations_reservations::dsl::accommodations_reservations
|
||||
.filter(accommodations_reservations::dsl::id.eq(r.id().0)),
|
||||
)
|
||||
.set((
|
||||
accommodations_reservations::dsl::time_update.eq(r.time_update),
|
||||
accommodations_reservations::dsl::validated.eq(r.validated),
|
||||
))
|
||||
.execute(conn)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get all the reservations of an accommodation
|
||||
pub async fn get_all_of_accommodation(
|
||||
id: AccommodationID,
|
||||
@ -33,3 +65,21 @@ pub async fn get_by_id(id: AccommodationReservationID) -> anyhow::Result<Accommo
|
||||
.get_result(conn)
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the reservations that are between a given interval of time for a given accommodation
|
||||
pub async fn get_reservations_for_time_interval(
|
||||
id: AccommodationID,
|
||||
start: usize,
|
||||
end: usize,
|
||||
) -> anyhow::Result<Vec<AccommodationReservation>> {
|
||||
db_connection::execute(|conn| {
|
||||
accommodations_reservations::table
|
||||
.filter(
|
||||
accommodations_reservations::dsl::accommodation_id
|
||||
.eq(id.0)
|
||||
.and(accommodations_reservations::dsl::reservation_start.lt((end) as i64))
|
||||
.and(accommodations_reservations::dsl::reservation_end.gt((start) as i64)),
|
||||
)
|
||||
.get_results(conn)
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user