Add an accommodations reservations module #188

Merged
pierre merged 81 commits from accomodation_module into master 2024-06-22 21:30:26 +00:00
9 changed files with 140 additions and 14 deletions
Showing only changes of commit b34959df33 - Show all commits

View File

@ -32,8 +32,8 @@ interface Constraints {
member_country: LenConstraint; member_country: LenConstraint;
member_sex: LenConstraint; member_sex: LenConstraint;
member_note: LenConstraint; member_note: LenConstraint;
accomodation_name_len: LenConstraint; accommodation_name_len: LenConstraint;
accomodation_description_len: LenConstraint; accommodation_description_len: LenConstraint;
} }
interface OIDCProvider { interface OIDCProvider {

View File

@ -61,8 +61,9 @@ pub struct StaticConstraints {
pub member_sex: SizeConstraint, pub member_sex: SizeConstraint,
pub member_note: SizeConstraint, pub member_note: SizeConstraint,
pub accomodation_name_len: SizeConstraint, pub accommodation_name_len: SizeConstraint,
pub accomodation_description_len: SizeConstraint, pub accommodation_description_len: SizeConstraint,
pub accommodation_calendar_name_len: SizeConstraint,
} }
impl Default for StaticConstraints { impl Default for StaticConstraints {
@ -95,8 +96,9 @@ impl Default for StaticConstraints {
member_sex: SizeConstraint::new(0, 1), member_sex: SizeConstraint::new(0, 1),
member_note: SizeConstraint::new(0, 35000), member_note: SizeConstraint::new(0, 35000),
accomodation_name_len: SizeConstraint::new(1, 50), accommodation_name_len: SizeConstraint::new(1, 50),
accomodation_description_len: SizeConstraint::new(0, 500), accommodation_description_len: SizeConstraint::new(0, 500),
accommodation_calendar_name_len: SizeConstraint::new(2, 50),
} }
} }
} }
@ -140,3 +142,6 @@ pub const THUMB_WIDTH: u32 = 350;
/// Thumbnail height /// Thumbnail height
pub const THUMB_HEIGHT: u32 = 350; pub const THUMB_HEIGHT: u32 = 350;
/// Accommodations reservations calendars tokens len
pub const ACCOMMODATIONS_RESERVATIONS_CALENDARS_TOKENS_LEN: usize = 50;

View File

@ -26,13 +26,13 @@ impl AccommodationRequest {
pub async fn to_accommodation(self, accommodation: &mut Accommodation) -> anyhow::Result<()> { pub async fn to_accommodation(self, accommodation: &mut Accommodation) -> anyhow::Result<()> {
let c = StaticConstraints::default(); let c = StaticConstraints::default();
if !c.accomodation_name_len.validate(&self.name) { if !c.accommodation_name_len.validate(&self.name) {
return Err(AccommodationListControllerErr::MalformedName.into()); return Err(AccommodationListControllerErr::MalformedName.into());
} }
accommodation.name = self.name; accommodation.name = self.name;
if let Some(d) = &self.description { if let Some(d) = &self.description {
if !c.accomodation_description_len.validate(d) { if !c.accommodation_description_len.validate(d) {
return Err(AccommodationListControllerErr::MalformedDescription.into()); return Err(AccommodationListControllerErr::MalformedDescription.into());
} }
} }

View File

@ -0,0 +1,52 @@
use crate::constants::StaticConstraints;
use crate::controllers::HttpResult;
use crate::extractors::family_extractor::FamilyInPath;
use crate::models::AccommodationID;
use crate::services::{accommodations_list_service, accommodations_reservations_calendars_service};
use actix_web::{web, HttpResponse};
#[derive(serde::Deserialize)]
pub struct CreateCalendarQuery {
accommodation_id: Option<AccommodationID>,
name: String,
}
/// Create a calendar
pub async fn create(a: FamilyInPath, req: web::Json<CreateCalendarQuery>) -> HttpResult {
let accommodation_id = match req.accommodation_id {
Some(i) => {
let accommodation = match accommodations_list_service::get_by_id(i).await {
Ok(a) => a,
Err(e) => {
log::error!("Failed to get accommodation information! {e}");
return Ok(HttpResponse::NotFound()
.json("The accommodation was not found in the family!"));
}
};
if accommodation.family_id() != a.family_id() {
return Ok(
HttpResponse::NotFound().json("The accommodation was not found in the family!")
);
}
Some(accommodation.id())
}
None => None,
};
let conf = StaticConstraints::default();
if !conf.accommodation_calendar_name_len.validate(&req.name) {
return Ok(HttpResponse::BadRequest().json("Invalid accommodation name!"));
}
let calendar = accommodations_reservations_calendars_service::create(
a.user_id(),
a.family_id(),
accommodation_id,
&req.name,
)
.await?;
Ok(HttpResponse::Ok().json(calendar))
}

View File

@ -6,6 +6,7 @@ use std::fmt::{Debug, Display, Formatter};
use zip::result::ZipError; use zip::result::ZipError;
pub mod accommodations_list_controller; pub mod accommodations_list_controller;
pub mod accommodations_reservations_calendars_controller;
pub mod accommodations_reservations_controller; pub mod accommodations_reservations_controller;
pub mod auth_controller; pub mod auth_controller;
pub mod couples_controller; pub mod couples_controller;

View File

@ -6,9 +6,10 @@ use actix_web::{web, App, HttpServer};
use geneit_backend::app_config::AppConfig; use geneit_backend::app_config::AppConfig;
use geneit_backend::connections::{db_connection, s3_connection}; use geneit_backend::connections::{db_connection, s3_connection};
use geneit_backend::controllers::{ use geneit_backend::controllers::{
accommodations_list_controller, accommodations_reservations_controller, auth_controller, accommodations_list_controller, accommodations_reservations_calendars_controller,
couples_controller, data_controller, families_controller, members_controller, accommodations_reservations_controller, auth_controller, couples_controller, data_controller,
photos_controller, server_controller, users_controller, families_controller, members_controller, photos_controller, server_controller,
users_controller,
}; };
#[actix_web::main] #[actix_web::main]
@ -257,7 +258,10 @@ async fn main() -> std::io::Result<()> {
web::post().to(accommodations_reservations_controller::validate_or_reject), web::post().to(accommodations_reservations_controller::validate_or_reject),
) )
// [ACCOMMODATIONS] Calendars controller // [ACCOMMODATIONS] Calendars controller
// TODO : create .route(
"/family/{id}/accommodations/reservations_calendars/create",
web::post().to(accommodations_reservations_calendars_controller::create),
)
// TODO : list // TODO : list
// TODO : delete // TODO : delete
// TODO : anonymous URL access // TODO : anonymous URL access

View File

@ -1,7 +1,7 @@
use crate::app_config::AppConfig; use crate::app_config::AppConfig;
use crate::schema::{ use crate::schema::{
accommodations_list, accommodations_reservations, couples, families, members, memberships, accommodations_list, accommodations_reservations, accommodations_reservations_cals_urls,
photos, users, couples, families, members, memberships, photos, users,
}; };
use crate::utils::crypt_utils::sha256; use crate::utils::crypt_utils::sha256;
use diesel::prelude::*; use diesel::prelude::*;
@ -527,3 +527,31 @@ pub struct NewAccommodationReservation {
pub reservation_start: i64, pub reservation_start: i64,
pub reservation_end: i64, pub reservation_end: i64,
} }
/// Accommodation reservation calendar ID holder
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash)]
pub struct AccommodationReservationCalendarID(pub i32);
#[derive(Queryable, Debug, serde::Serialize)]
pub struct AccommodationReservationCalendar {
id: i32,
family_id: i32,
accommodation_id: Option<i32>,
user_id: i32,
name: String,
token: String,
pub time_create: i64,
pub time_used: i64,
}
#[derive(Insertable)]
#[diesel(table_name = accommodations_reservations_cals_urls)]
pub struct NewAccommodationReservationCalendar {
pub family_id: i32,
pub accommodation_id: Option<i32>,
pub user_id: i32,
pub name: String,
pub token: String,
pub time_create: i64,
pub time_used: i64,
}

View File

@ -0,0 +1,35 @@
use crate::connections::db_connection;
use crate::constants;
use crate::models::{
AccommodationID, AccommodationReservationCalendar, FamilyID,
NewAccommodationReservationCalendar, UserID,
};
use crate::schema::accommodations_reservations_cals_urls;
use crate::utils::string_utils::rand_str;
use crate::utils::time_utils::time;
use diesel::prelude::*;
/// Create a new reservation calendar entry
pub async fn create(
user_id: UserID,
family_id: FamilyID,
accommodation_id: Option<AccommodationID>,
name: &str,
) -> anyhow::Result<AccommodationReservationCalendar> {
db_connection::execute(|conn| {
let res: AccommodationReservationCalendar =
diesel::insert_into(accommodations_reservations_cals_urls::table)
.values(&NewAccommodationReservationCalendar {
family_id: family_id.0,
accommodation_id: accommodation_id.map(|i| i.0),
user_id: user_id.0,
name: name.to_string(),
token: rand_str(constants::ACCOMMODATIONS_RESERVATIONS_CALENDARS_TOKENS_LEN),
time_create: time() as i64,
time_used: time() as i64,
})
.get_result(conn)?;
Ok(res)
})
}

View File

@ -1,6 +1,7 @@
//! # Backend services //! # Backend services
pub mod accommodations_list_service; pub mod accommodations_list_service;
pub mod accommodations_reservations_calendars_service;
pub mod accommodations_reservations_service; pub mod accommodations_reservations_service;
pub mod couples_service; pub mod couples_service;
pub mod families_service; pub mod families_service;