Can change a reservation time
This commit is contained in:
		@@ -2,50 +2,67 @@ 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::models::{Accommodation, AccommodationReservationID, NewAccommodationReservation};
 | 
			
		||||
use crate::services::accommodations_reservations_service;
 | 
			
		||||
use crate::utils::time_utils::time;
 | 
			
		||||
use actix_web::{web, HttpResponse};
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Deserialize)]
 | 
			
		||||
pub struct CreateReservationQuery {
 | 
			
		||||
pub struct UpdateReservationQuery {
 | 
			
		||||
    start: usize,
 | 
			
		||||
    end: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl UpdateReservationQuery {
 | 
			
		||||
    /// Check whether a reservation request is valid or not
 | 
			
		||||
    async fn validate(
 | 
			
		||||
        &self,
 | 
			
		||||
        a: &Accommodation,
 | 
			
		||||
        resa_id: Option<AccommodationReservationID>,
 | 
			
		||||
    ) -> anyhow::Result<Option<&str>> {
 | 
			
		||||
        if !a.open_to_reservations {
 | 
			
		||||
            return Ok(Some(
 | 
			
		||||
                "The accommodation is not open to reservations create / update!",
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (self.start as i64) < (time() as i64 - 3600 * 24 * 30) {
 | 
			
		||||
            return Ok(Some("Start time is too far in the past!"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if self.start == self.end {
 | 
			
		||||
            return Ok(Some("Start and end time must be different!"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if self.start > self.end {
 | 
			
		||||
            return Ok(Some("End time happens before start time!"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let existing = accommodations_reservations_service::get_reservations_for_time_interval(
 | 
			
		||||
            a.id(),
 | 
			
		||||
            self.start,
 | 
			
		||||
            self.end,
 | 
			
		||||
        )
 | 
			
		||||
        .await?;
 | 
			
		||||
 | 
			
		||||
        if existing
 | 
			
		||||
            .iter()
 | 
			
		||||
            .any(|r| r.validated != Some(false) && resa_id != Some(r.id()))
 | 
			
		||||
        {
 | 
			
		||||
            return Ok(Some("This reservation is in conflict with another one!"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(None)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Create a reservation
 | 
			
		||||
pub async fn create_reservation(
 | 
			
		||||
    a: FamilyAndAccommodationInPath,
 | 
			
		||||
    req: web::Json<CreateReservationQuery>,
 | 
			
		||||
    req: web::Json<UpdateReservationQuery>,
 | 
			
		||||
) -> 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("Start and end time must be different!"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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!")
 | 
			
		||||
        );
 | 
			
		||||
    if let Some(err) = req.validate(&a, None).await? {
 | 
			
		||||
        return Ok(HttpResponse::BadRequest().json(err));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut reservation =
 | 
			
		||||
@@ -87,6 +104,36 @@ pub async fn get_single(m: FamilyAndAccommodationReservationInPath) -> HttpResul
 | 
			
		||||
    Ok(HttpResponse::Ok().json(m.to_reservation()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Update a reservation
 | 
			
		||||
pub async fn update_single(
 | 
			
		||||
    m: FamilyAndAccommodationReservationInPath,
 | 
			
		||||
    req: web::Json<UpdateReservationQuery>,
 | 
			
		||||
) -> HttpResult {
 | 
			
		||||
    if let Some(err) = req.validate(m.as_accommodation(), Some(m.id())).await? {
 | 
			
		||||
        return Ok(HttpResponse::BadRequest().json(err));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if m.membership().user_id() != m.user_id() {
 | 
			
		||||
        return Ok(
 | 
			
		||||
            HttpResponse::BadRequest().json("Only the owner of a reservation can change it!")
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let need_validation = m.as_accommodation().need_validation;
 | 
			
		||||
 | 
			
		||||
    let mut reservation = m.to_reservation();
 | 
			
		||||
    reservation.reservation_start = req.start as i64;
 | 
			
		||||
    reservation.reservation_end = req.end as i64;
 | 
			
		||||
 | 
			
		||||
    if need_validation {
 | 
			
		||||
        reservation.validated = None;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    accommodations_reservations_service::update(&mut reservation).await?;
 | 
			
		||||
 | 
			
		||||
    Ok(HttpResponse::Accepted().finish())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Delete a reservation
 | 
			
		||||
pub async fn delete(m: FamilyAndAccommodationReservationInPath) -> HttpResult {
 | 
			
		||||
    if m.membership().user_id() != m.user_id() {
 | 
			
		||||
 
 | 
			
		||||
@@ -60,6 +60,10 @@ impl FamilyAndAccommodationReservationInPath {
 | 
			
		||||
        &self.0
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn as_accommodation(&self) -> &Accommodation {
 | 
			
		||||
        &self.1
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_accommodation(self) -> Accommodation {
 | 
			
		||||
        self.1
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -244,7 +244,10 @@ async fn main() -> std::io::Result<()> {
 | 
			
		||||
                "/family/{id}/accommodations/reservation/{reservation_id}",
 | 
			
		||||
                web::get().to(accommodations_reservations_controller::get_single),
 | 
			
		||||
            )
 | 
			
		||||
            // TODO : update
 | 
			
		||||
            .route(
 | 
			
		||||
                "/family/{id}/accommodations/reservation/{reservation_id}",
 | 
			
		||||
                web::patch().to(accommodations_reservations_controller::update_single),
 | 
			
		||||
            )
 | 
			
		||||
            .route(
 | 
			
		||||
                "/family/{id}/accommodations/reservation/{reservation_id}",
 | 
			
		||||
                web::delete().to(accommodations_reservations_controller::delete),
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,8 @@ pub async fn update(r: &mut AccommodationReservation) -> anyhow::Result<()> {
 | 
			
		||||
        .set((
 | 
			
		||||
            accommodations_reservations::dsl::time_update.eq(r.time_update),
 | 
			
		||||
            accommodations_reservations::dsl::validated.eq(r.validated),
 | 
			
		||||
            accommodations_reservations::dsl::reservation_start.eq(r.reservation_start),
 | 
			
		||||
            accommodations_reservations::dsl::reservation_end.eq(r.reservation_end),
 | 
			
		||||
        ))
 | 
			
		||||
        .execute(conn)
 | 
			
		||||
    })?;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user