use chrono::{Duration, Local}; use futures::future; use sqlx::{query, query_as}; use terminwahl_typen::{IdType, Nutzer, PlannedAppointment}; use crate::api::write::AppointmentTeacherSlot; use super::Pool; pub async fn save_appointments( pool: &Pool, appointments: &[PlannedAppointment], nutzer_id: IdType, validation_key: &str, ) -> Result<(), sqlx::Error> { for appointment in appointments { let _ = query!("DELETE FROM appointments WHERE datetime(expires) < datetime('now');") .execute(pool) .await; let now = Local::now().naive_local(); let in_three_hours = now + Duration::hours(3); query!( "INSERT INTO appointments (teacher_id, slot_id, nutzer_id, validation_key, expires) VALUES ($1, $2, $3, $4, $5)", appointment.teacher_id, appointment.slot_id, nutzer_id, validation_key, in_three_hours ) .execute(pool) .await?; } Ok(()) } pub async fn save_nutzer(pool: &Pool, nutzer: &Nutzer) -> Result { query!( "INSERT INTO nutzer (name, schueler, email) VALUES ($1, $2, $3)", nutzer.name, nutzer.schüler, nutzer.email ) .execute(pool) .await?; let db_nutzer = query!( "SELECT id FROM nutzer WHERE name = ? and email = ?", nutzer.name, nutzer.email ) .fetch_one(pool) .await?; Ok(db_nutzer.id) } pub async fn confirm_appointments( pool: &Pool, validation_key: &str, ) -> Result, sqlx::Error> { let _ = query!( "UPDATE appointments SET expires = NULL WHERE validation_key = ?", validation_key ) .execute(pool) .await?; let appointments = query_as!( PlannedAppointment, "Select teacher_id, slot_id from appointments WHERE validation_key = ? and expires is NULL", validation_key ) .fetch_all(pool) .await?; let full_appointments = future::try_join_all(appointments.into_iter().map( |PlannedAppointment { teacher_id, slot_id, }| { AppointmentTeacherSlot::get(pool, teacher_id, slot_id) }, )) .await .expect("Failed to get full list of appointments"); Ok(full_appointments) } pub async fn cancel_appointment( pool: &Pool, teacher_id: IdType, slot_id: IdType, validation_key: &str, ) -> Result, sqlx::Error> { let _ = query!( "DELETE FROM appointments WHERE teacher_id = ? AND slot_id = ? AND validation_key = ?", teacher_id, slot_id, validation_key ) .execute(pool) .await?; // Fetch the remaining appointments let appointments = query_as!( PlannedAppointment, "Select teacher_id, slot_id from appointments WHERE validation_key = ? and expires is NULL", validation_key ) .fetch_all(pool) .await?; // Fetch the teacher names and times let full_appointments = future::try_join_all(appointments.into_iter().map( |PlannedAppointment { teacher_id, slot_id, }| { AppointmentTeacherSlot::get(pool, teacher_id, slot_id) }, )) .await .expect("Failed to get full list of appointments"); Ok(full_appointments) }