GeneIT/geneit_backend/src/controllers/accommodations_reservations_calendars_controller.rs
Pierre HUBERT df6a9e8292
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Can generate calendars
2024-06-03 22:47:39 +02:00

158 lines
5.2 KiB
Rust

use ical::{generator::*, *};
use actix_web::{web, HttpResponse};
use chrono::DateTime;
use crate::constants::StaticConstraints;
use crate::controllers::HttpResult;
use crate::extractors::accommodation_reservation_calendar_extractor::FamilyAndAccommodationReservationCalendarInPath;
use crate::extractors::family_extractor::FamilyInPath;
use crate::models::{AccommodationID, ReservationStatus};
use crate::services::{
accommodations_list_service, accommodations_reservations_calendars_service,
accommodations_reservations_service, families_service,
};
#[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))
}
/// Get the list of calendars of a user
pub async fn get_list(a: FamilyInPath) -> HttpResult {
let users =
accommodations_reservations_calendars_service::get_all_of_user(a.user_id(), a.family_id())
.await?;
Ok(HttpResponse::Ok().json(users))
}
/// Delete a calendar
pub async fn delete(resa: FamilyAndAccommodationReservationCalendarInPath) -> HttpResult {
accommodations_reservations_calendars_service::delete(resa.to_reservation()).await?;
Ok(HttpResponse::Ok().json("Calendar successfully deleted"))
}
fn fmt_date(time: i64) -> String {
let res = DateTime::from_timestamp(time, 0).expect("Failed to parse date");
/*format!(
"{:0>4}{:0>2}{:0>2}T{:0>2}{:0>2}",
res.year(),
res.month(),
res.day(),
res.minute(),
res.second()
)*/
res.format("%Y%m%dT%H%M%S").to_string()
}
#[derive(serde::Deserialize)]
pub struct AnonymousAccessURL {
token: String,
}
/// Get the content of the calendar
pub async fn anonymous_access(req: web::Path<AnonymousAccessURL>) -> HttpResult {
let calendar =
match accommodations_reservations_calendars_service::get_by_token(&req.token).await {
Ok(c) => c,
Err(e) => {
log::error!("Calendar information could not be retrieved: {e}");
return Ok(HttpResponse::NotFound().body("Calendar not found!"));
}
};
let accommodations =
accommodations_list_service::get_all_of_family(calendar.family_id()).await?;
let members = families_service::get_memberships_of_family(calendar.family_id()).await?;
// Get calendar associated events
let events = match calendar.accommodation_id() {
None => {
accommodations_reservations_service::get_all_of_family(calendar.family_id()).await?
}
Some(a) => accommodations_reservations_service::get_all_of_accommodation(a).await?,
};
let mut cal = IcalCalendarBuilder::version("2.0")
.gregorian()
.prodid("-//geneit//")
.build();
for ev in events {
let accommodation = accommodations
.iter()
.find(|a| a.id() == ev.accommodation_id())
.unwrap();
let member_name = members
.iter()
.find(|a| a.membership.user_id() == ev.user_id())
.map(|m| m.user_name.as_str())
.unwrap_or("other user");
let event = IcalEventBuilder::tzid("Europe/Paris")
.uid(format!("resa-{}", ev.id().0))
.changed(fmt_date(ev.time_update))
.start(fmt_date(ev.reservation_start))
.end(fmt_date(ev.reservation_end))
.set(ical_property!("SUMMARY", member_name))
.set(ical_property!("LOCATION", &accommodation.name))
.set(ical_property!(
"STATUS",
match ev.status() {
ReservationStatus::Pending => "TENTATIVE",
ReservationStatus::Accepted => "CONFIRMED",
ReservationStatus::Rejected => "CANCELLED",
}
))
.build();
cal.events.push(event);
}
Ok(HttpResponse::Ok()
.content_type("text/calendar")
.body(cal.generate()))
}