add notification to all pot. coxes if trip is full

This commit is contained in:
philipp 2024-04-15 18:16:43 +02:00
parent 1869b36e09
commit 74505c1554
3 changed files with 69 additions and 3 deletions

View File

@ -30,12 +30,12 @@ pub struct Trip {
pub struct TripWithUserAndType {
#[serde(flatten)]
pub trip: Trip,
rower: Vec<Registration>,
pub rower: Vec<Registration>,
trip_type: Option<TripType>,
}
impl TripWithUserAndType {
async fn from(db: &SqlitePool, trip: Trip) -> Self {
pub async fn from(db: &SqlitePool, trip: Trip) -> Self {
let mut trip_type = None;
if let Some(trip_type_id) = trip.trip_type_id {
trip_type = TripType::find_by_id(db, trip_type_id).await;
@ -230,6 +230,9 @@ WHERE day=?
}
}
let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap();
trip_details.check_free_spaces(db).await;
Ok(())
}

View File

@ -4,6 +4,11 @@ use rocket::FromForm;
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, SqlitePool};
use super::{
notification::Notification,
trip::{Trip, TripWithUserAndType},
};
#[derive(FromRow, Debug, Serialize, Deserialize)]
pub struct TripDetails {
pub id: i64,
@ -64,6 +69,57 @@ WHERE day = ? AND planned_starting_time = ?
.await.unwrap()
}
/// This function is called when a person registers to a trip or when the cox changes the
/// amount of free places.
pub async fn check_free_spaces(&self, db: &SqlitePool) {
if !self.is_full(db).await {
// We still have space for new people, no need to do anything
return;
}
let other_trips_same_time = Self::find_by_startingdatetime(
db,
self.day.clone(),
self.planned_starting_time.clone(),
)
.await;
for trip in &other_trips_same_time {
if !trip.is_full(db).await {
// There are trips on the same time, with open places
return;
}
}
// We just got fully booked and there are no other trips with remaining rower places. Send
// notification to all coxes which are registered as non-cox.
for trip_details in other_trips_same_time {
let Some(trip) = Trip::find_by_trip_details(db, trip_details.id).await else {
// This trip_details belongs to a planned_event, no need to do anything
continue;
};
let pot_coxes = TripWithUserAndType::from(db, trip.clone()).await;
let pot_coxes = pot_coxes.rower;
for user in pot_coxes {
let cox = User::find_by_id(db, trip.cox_id as i32).await.unwrap();
let Some(user) = User::find_by_name(db, &user.name).await else {
// User is a guest, no need to bother.
continue;
};
if !user.has_role(db, "cox").await {
// User is no cox, no need to bother
continue;
}
if user.id == cox.id {
// User already offers a trip, no need to bother
continue;
}
Notification::create(db, &user, &format!("Du hast dich als Ruderer bei der Ausfahrt von {} am {} um {} angemeldet. Bei allen Ausfahrten zu dieser Zeit sind nun alle Plätze ausgebucht. Damit noch mehr (Nicht-Steuerleute) mitfahren können, wäre es super, wenn du eine eigene Ausfahrt zur selben Zeit ausschreiben könntest.", cox.name, self.day, self.planned_starting_time), "Volle Ausfahrt", None).await;
}
}
}
/// Creates a new entry in `trip_details` and returns its id.
pub async fn create(db: &SqlitePool, tripdetails: TripDetailsToAdd<'_>) -> i64 {
let query = sqlx::query!(

View File

@ -1,6 +1,11 @@
use sqlx::SqlitePool;
use super::{notification::Notification, trip::Trip, tripdetails::TripDetails, user::User};
use super::{
notification::Notification,
trip::{Trip, TripWithUserAndType},
tripdetails::TripDetails,
user::User,
};
use crate::model::tripdetails::{Action, CoxAtTrip::Yes};
pub struct UserTrip {}
@ -79,6 +84,8 @@ impl UserTrip {
None,
)
.await;
trip_details.check_free_spaces(db).await;
}
Ok(name_newly_registered_person)