161 lines
4.0 KiB
Rust

use std::collections::HashSet;
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use sqlx::query_as;
use terminwahl_typen::{
AppointmentSlot, AppointmentSlots, IdType, Nutzer, SlotId, Subject, Subjects, Teacher, Teachers,
};
use super::Pool;
pub async fn get_teachers(db: &Pool) -> Result<Teachers, sqlx::Error> {
query_as!(
Teacher,
r#"
SELECT *
FROM `teachers`"#,
)
.fetch_all(db)
.await
}
pub async fn get_teacher_by_id(db: &Pool, teacher_id: IdType) -> Result<Teacher, sqlx::Error> {
query_as!(
Teacher,
r#"
SELECT *
FROM `teachers` WHERE id = ?"#,
teacher_id
)
.fetch_one(db)
.await
}
pub async fn get_subjects(db: &Pool) -> Result<Subjects, sqlx::Error> {
query_as!(
Subject,
r#"
SELECT *
FROM `subjects`"#,
)
.fetch_all(db)
.await
}
pub async fn get_slots(db: &Pool) -> Result<AppointmentSlots, sqlx::Error> {
match query_as!(
AppointmentSlot,
r#"
SELECT *
FROM `appointment_slots`"#,
)
.fetch_all(db)
.await
{
Ok(elems) => Ok(elems.into_iter().map(|e| (e.id, e)).collect()),
Err(e) => Err(e),
}
}
pub async fn get_slot_by_id(db: &Pool, slot_id: IdType) -> Result<AppointmentSlot, sqlx::Error> {
match query_as!(
AppointmentSlot,
r#"
SELECT *
FROM `appointment_slots` WHERE id = ?"#,
slot_id
)
.fetch_one(db)
.await
{
Ok(slot) => Ok(slot),
Err(e) => Err(e),
}
}
pub async fn get_unavailable(db: &Pool) -> Result<HashSet<SlotId>, sqlx::Error> {
match query_as!(
SlotId,
r#"
SELECT teacher_id, slot_id
FROM `appointments` WHERE datetime(expires) > datetime('now') OR expires is NULL;"#,
)
.fetch_all(db)
.await
{
Ok(elems) => Ok(elems.into_iter().collect()),
Err(e) => Err(e),
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct TeacherWithAppointments {
teacher: Teacher,
appointments: Vec<AssignedAppointment>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct FullAppointment {
id: IdType,
teacher_id: IdType,
slot_id: IdType,
nutzer_id: IdType,
expires: Option<NaiveDateTime>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct AssignedAppointment {
appointment: FullAppointment,
slot: AppointmentSlot,
nutzer: Nutzer,
}
pub async fn get_all_teachers(db: &Pool) -> Result<Vec<TeacherWithAppointments>, sqlx::Error> {
let teachers = get_teachers(db).await?;
let mut response = Vec::new();
for teacher in teachers.into_iter() {
let teacher_id: i64 = teacher.id;
let mut appointments: Vec<FullAppointment> = query_as!(
FullAppointment,
r#"
SELECT id,teacher_id,slot_id,nutzer_id,expires
FROM `appointments` WHERE teacher_id = ?"#,
teacher_id
)
.fetch_all(db)
.await?;
appointments.sort_by(|a, b| a.slot_id.cmp(&b.slot_id));
let mut assigned_appointments: Vec<AssignedAppointment> = Vec::new();
for appointment in appointments.into_iter() {
let slot = query_as!(
AppointmentSlot,
r#"
SELECT *
FROM `appointment_slots` WHERE id = ? "#,
appointment.slot_id
)
.fetch_one(db)
.await?;
let nutzer = query_as!(
Nutzer,
r#"
SELECT name, schueler as schueler,email
FROM `nutzer` WHERE id = ? "#,
appointment.nutzer_id
)
.fetch_one(db)
.await?;
assigned_appointments.push(AssignedAppointment {
appointment,
slot,
nutzer,
})
}
response.push(TeacherWithAppointments {
teacher,
appointments: assigned_appointments,
})
}
Ok(response)
}