bvplan/backend/src/graphql.rs
2023-01-17 06:54:45 +01:00

324 lines
7.9 KiB
Rust

use diesel::prelude::*;
use juniper::{graphql_object, EmptyMutation, EmptySubscription, FieldResult, RootNode};
use r2d2_redis::redis;
use std::ops::DerefMut;
use crate::{cache, db};
#[derive(Clone)]
pub struct Context;
impl juniper::Context for Context {}
pub struct Schoolyear {
pub model: db::models::Schoolyear,
}
#[graphql_object]
impl Schoolyear {
fn id(&self) -> i32 {
self.model.id
}
fn untis_id(&self) -> i32 {
self.model.untis_id
}
fn name(&self) -> &str {
self.model.name.as_str()
}
fn start_date(&self) -> chrono::NaiveDate {
self.model.start_date
}
fn end_date(&self) -> chrono::NaiveDate {
self.model.end_date
}
}
pub struct Teacher {
pub model: db::models::Teacher,
}
#[graphql_object]
impl Teacher {
fn id(&self) -> i32 {
self.model.id
}
fn untis_id(&self) -> i32 {
self.model.untis_id
}
fn schoolyear(&self) -> FieldResult<Schoolyear> {
let db_conn = &mut db::POOL.get()?;
Ok(Schoolyear {
model: db::schema::schoolyears::table
.filter(db::schema::schoolyears::id.eq(self.model.schoolyear_id))
.first::<db::models::Schoolyear>(db_conn)?,
})
}
fn name(&self) -> &str {
&self.model.name
}
fn forename(&self) -> Option<&str> {
self.model.forename.as_deref()
}
fn display_name(&self) -> &str {
&self.model.display_name
}
}
pub struct Class {
pub model: db::models::Class,
}
#[graphql_object]
impl Class {
fn id(&self) -> i32 {
self.model.id
}
fn untis_id(&self) -> i32 {
self.model.untis_id
}
fn schoolyear(&self) -> FieldResult<Schoolyear> {
let db_conn = &mut db::POOL.get()?;
Ok(Schoolyear {
model: db::schema::schoolyears::table
.filter(db::schema::schoolyears::id.eq(self.model.schoolyear_id))
.first::<db::models::Schoolyear>(db_conn)?,
})
}
fn name(&self) -> &str {
&self.model.name
}
fn long_name(&self) -> &str {
&self.model.long_name
}
fn active(&self) -> bool {
self.model.active
}
}
pub struct SubstitutionClass {
pub model: db::models::SubstitutionClass,
}
#[graphql_object]
impl SubstitutionClass {
fn id(&self) -> i32 {
self.model.id
}
fn substitution(&self) -> FieldResult<Substitution> {
let db_conn = &mut db::POOL.get()?;
Ok(Substitution {
model: db::schema::substitutions::table
.filter(db::schema::substitutions::id.eq(self.model.substitution_id))
.first::<db::models::Substitution>(db_conn)?,
})
}
fn position(&self) -> i32 {
self.model.position as i32
}
fn class(&self) -> FieldResult<Class> {
let db_conn = &mut db::POOL.get()?;
Ok(Class {
model: db::schema::classes::table
.filter(db::schema::classes::id.eq(self.model.class_id))
.first::<db::models::Class>(db_conn)?,
})
}
}
pub struct SubstitutionTeacher {
pub model: db::models::SubstitutionTeacher,
}
#[graphql_object]
impl SubstitutionTeacher {
fn id(&self) -> i32 {
self.model.id
}
fn substitution(&self) -> FieldResult<Substitution> {
let db_conn = &mut db::POOL.get()?;
Ok(Substitution {
model: db::schema::substitutions::table
.filter(db::schema::substitutions::id.eq(self.model.substitution_id))
.first::<db::models::Substitution>(db_conn)?,
})
}
fn position(&self) -> i32 {
self.model.position as i32
}
fn teacher(&self) -> FieldResult<Option<Teacher>> {
if let Some(teacher_id) = self.model.teacher_id {
let db_conn = &mut db::POOL.get()?;
Ok(Some(Teacher {
model: db::schema::teachers::table
.filter(db::schema::teachers::id.eq(teacher_id))
.first::<db::models::Teacher>(db_conn)?,
}))
} else {
Ok(None)
}
}
}
pub struct Substitution {
pub model: db::models::Substitution,
}
#[graphql_object]
impl Substitution {
fn id(&self) -> i32 {
self.model.id
}
fn substitution_query(&self) -> FieldResult<SubstitutionQuery> {
let db_conn = &mut db::POOL.get()?;
Ok(SubstitutionQuery {
model: db::schema::substitution_queries::table
.filter(db::schema::substitution_queries::id.eq(self.model.substitution_query_id))
.first::<db::models::SubstitutionQuery>(db_conn)?,
})
}
fn subst_type(&self) -> db::models::SubstitutionType {
self.model.subst_type.to_owned()
}
fn lesson_id(&self) -> i32 {
self.model.lesson_id
}
fn start_time(&self) -> chrono::NaiveTime {
self.model.start_time
}
fn end_time(&self) -> chrono::NaiveTime {
self.model.end_time
}
fn text(&self) -> Option<&str> {
self.model.text.as_deref()
}
fn classes(&self) -> FieldResult<Vec<SubstitutionClass>> {
let db_conn = &mut db::POOL.get()?;
Ok(db::schema::substitution_classes::table
.filter(db::schema::substitution_classes::substitution_id.eq(self.model.id))
.load::<db::models::SubstitutionClass>(db_conn)?
.into_iter()
.map(|x| SubstitutionClass { model: x })
.collect())
}
}
pub struct SubstitutionQuery {
pub model: db::models::SubstitutionQuery,
}
#[graphql_object]
impl SubstitutionQuery {
fn id(&self) -> i32 {
self.model.id
}
fn schoolyear(&self) -> FieldResult<Schoolyear> {
let db_conn = &mut db::POOL.get()?;
Ok(Schoolyear {
model: db::schema::schoolyears::table
.filter(db::schema::schoolyears::id.eq(self.model.schoolyear_id))
.first::<db::models::Schoolyear>(db_conn)?,
})
}
fn date(&self) -> chrono::NaiveDate {
self.model.date
}
fn week_type(&self) -> db::models::WeekType {
self.model.week_type.to_owned()
}
fn queried_at(&self) -> chrono::NaiveDateTime {
self.model.queried_at
}
fn substitutions(&self) -> FieldResult<Vec<Substitution>> {
let db_conn = &mut db::POOL.get()?;
Ok(db::schema::substitutions::table
.filter(db::schema::substitutions::substitution_query_id.eq(self.model.id))
.load::<db::models::Substitution>(db_conn)?
.into_iter()
.map(|x| Substitution { model: x })
.collect())
}
}
pub struct Query;
#[graphql_object(context = Context)]
impl Query {
fn ping() -> &'static str {
"pong"
}
fn last_substitution_query() -> FieldResult<SubstitutionQuery> {
let db_conn = &mut db::POOL.get()?;
let redis_conn = &mut cache::POOL.get()?;
let id = redis::cmd("GET")
.arg(cache::keys::LAST_SUBSTITUTION_QUERY_ID)
.query::<Option<i32>>(redis_conn.deref_mut())?
.map_or_else(
|| {
db::schema::substitution_queries::table
.select(db::schema::substitution_queries::id)
.order(db::schema::substitution_queries::queried_at.desc())
.first::<i32>(db_conn)
},
|x| Ok(x),
)?;
let last_query = db::schema::substitution_queries::table
.filter(db::schema::substitution_queries::id.eq(id))
.first::<db::models::SubstitutionQuery>(db_conn)?;
Ok(SubstitutionQuery { model: last_query })
}
}
pub type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
pub fn schema() -> Schema {
Schema::new(
Query,
EmptyMutation::<Context>::new(),
EmptySubscription::<Context>::new(),
)
}