Implemented admin overview.

This commit is contained in:
2024-02-05 12:00:38 +01:00
parent 6c7fd2e46f
commit e69db7f40b
9 changed files with 402 additions and 74 deletions
+23
View File
@@ -447,6 +447,22 @@ pub struct Reservation {
pub summary: i32,
}
#[derive(Clone, Serialize, Deserialize, Debug, Default)]
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
pub struct ResPropertyView {
pub name: String,
pub description: String
}
#[derive(Clone, Serialize, Deserialize, Debug, Default)]
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
pub struct ResWithProperty {
#[cfg_attr(feature = "ssr", sqlx(flatten))]
pub reservation: Reservation,
#[cfg_attr(feature = "ssr", sqlx(flatten))]
pub property: ResPropertyView
}
pub struct Reservations(Vec<Reservation>);
// Transform slots to reservations
@@ -515,6 +531,13 @@ impl ReservationSum {
}
}
#[derive(Clone, Serialize, Deserialize, Debug, Default)]
pub struct ResSumWithItems {
pub summary: ReservationSum,
pub customer: Customer,
pub reservations: Vec<ResWithProperty>
}
/*
pub enum MessageType {
NewReservation,
+116 -3
View File
@@ -1,18 +1,19 @@
use leptos::*;
use validator::Validate;
use crate::backend::data::{ApiResponse, CrReservation, Reservation, PublicFormData};
use crate::backend::data::{ApiResponse, CrReservation, Reservation, PublicFormData, ResSumWithItems};
use crate::components::data_form::ForValidation;
use cfg_if::cfg_if;
use chrono::{NaiveDate, NaiveTime};
cfg_if! { if #[cfg(feature = "ssr")] {
use sqlx::{Postgres, Transaction};
use sqlx::{Postgres, Transaction, query};
use sqlx::query_as;
use sqlx::Error;
use uuid::Uuid;
use std::ops::DerefMut;
use std::str::FromStr;
use crate::backend::data::ReservationSum;
use futures_util::future::join_all;
use crate::backend::data::{ReservationSum, ReservationState, ResWithProperty, Customer};
use crate::backend::get_pool;
async fn find_sum_by_uuid(uuid: &Uuid, tx: &mut Transaction<'_, Postgres>) -> Result<ReservationSum, Error> {
@@ -41,6 +42,70 @@ cfg_if! { if #[cfg(feature = "ssr")] {
Ok(reservations?)
}
}
async fn reservations_in_range(from: &NaiveDate, to: &NaiveDate, state: Option<ReservationState>) -> Result<Vec<ResSumWithItems>, ServerFnError> {
let pool = get_pool().await?;
let sums = if let Some(s) = state {
query_as::<_, ReservationSum>("SELECT * FROM reservation_sum WHERE date >= $1 AND date <= $2 AND state = $3 ORDER BY date")
.bind(from)
.bind(to)
.bind(s)
.fetch_all(&pool)
.await
} else {
query_as::<_, ReservationSum>("SELECT * FROM reservation_sum WHERE date >= $1 AND date <= $2 ORDER BY date")
.bind(from)
.bind(to)
.fetch_all(&pool)
.await
};
let sums = if let Err(ref e) = sums {
if matches!(e, Error::RowNotFound) {
vec![]
} else {
sums?
}
} else {
sums?
};
if sums.is_empty() {
return Ok(vec![])
}
let res: Result<Vec<ResSumWithItems>, Error> = join_all(sums.into_iter().map(|s| async {
let reservations = query_as::<_, ResWithProperty>(
"SELECT r.id, r.from, r.to, r.property, r.summary, p.name, p,description \
FROM reservation as r \
JOIN property as p ON r.property = p.id WHERE r.summary = $1")
.bind(s.id())
.fetch_all(&pool)
.await?;
let customer = query_as::<_, Customer>("SELECT * FROM customer WHERE id = $1")
.bind(s.customer)
.fetch_one(&pool)
.await?;
Ok(ResSumWithItems {
summary: s,
customer,
reservations
})
})).await.into_iter().collect();
Ok(res?)
}
async fn set_state(uuid: Uuid, state: ReservationState) -> Result<(), ServerFnError> {
let pool = get_pool().await?;
query("UPDATE reservation_sum SET state = $1 WHERE uuid = $2")
.bind(state)
.bind(uuid)
.execute(&pool)
.await?;
Ok(())
}
}}
#[server]
@@ -148,4 +213,52 @@ impl ForValidation for CreateReservation {
fn entity(&self) -> &dyn Validate {
&self.reservation
}
}
#[server]
pub async fn get_new_reservations() -> Result<ApiResponse<Vec<ResSumWithItems>>, ServerFnError> {
use crate::perm_check;
use chrono::{Days, Local};
use crate::backend::data::ReservationState;
perm_check!(is_logged_in);
Ok(ApiResponse::Data(reservations_in_range(&Local::now().date_naive(),
&Local::now().checked_add_days(Days::new(7)).unwrap().date_naive(),
Some(ReservationState::New)).await?))
}
#[server]
pub async fn get_next_reservations() -> Result<ApiResponse<Vec<ResSumWithItems>>, ServerFnError> {
use crate::perm_check;
use chrono::{Days, Local};
use crate::backend::data::ReservationState;
perm_check!(is_logged_in);
Ok(ApiResponse::Data(reservations_in_range(&Local::now().date_naive(),
&Local::now().checked_add_days(Days::new(7)).unwrap().date_naive(),
Some(ReservationState::Approved)).await?))
}
#[server]
pub async fn approve(uuid: String) -> Result<ApiResponse<()>, ServerFnError> {
use crate::perm_check;
use crate::backend::data::ReservationState;
perm_check!(is_logged_in);
set_state(Uuid::parse_str(&uuid)?, ReservationState::Approved).await?;
Ok(ApiResponse::Data(()))
}
#[server]
pub async fn cancel(uuid: String) -> Result<ApiResponse<()>, ServerFnError> {
use crate::perm_check;
use crate::backend::data::ReservationState;
perm_check!(is_logged_in);
set_state(Uuid::parse_str(&uuid)?, ReservationState::Canceled).await?;
Ok(ApiResponse::Data(()))
}