Update
This commit is contained in:
parent
19c3d876a2
commit
b25c20ab69
10 changed files with 472 additions and 365 deletions
|
@ -26,6 +26,7 @@ LABEL maintainer="Dominic Grimm <dominic@dergrimm.net>" \
|
||||||
RUN apt update
|
RUN apt update
|
||||||
RUN apt install -y libpq5
|
RUN apt install -y libpq5
|
||||||
RUN apt install -y ca-certificates
|
RUN apt install -y ca-certificates
|
||||||
|
RUN apt install -y tzdata
|
||||||
RUN apt-get clean
|
RUN apt-get clean
|
||||||
RUN apt-get autoremove -y
|
RUN apt-get autoremove -y
|
||||||
RUN rm -rf /var/lib/{apt,dpkg,cache,log}/
|
RUN rm -rf /var/lib/{apt,dpkg,cache,log}/
|
||||||
|
|
|
@ -125,7 +125,7 @@ CREATE TABLE timegrid_time_unit (
|
||||||
CREATE TYPE week_type AS ENUM ('a', 'b');
|
CREATE TYPE week_type AS ENUM ('a', 'b');
|
||||||
|
|
||||||
CREATE TABLE substitution_queries (
|
CREATE TABLE substitution_queries (
|
||||||
id SERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
|
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
|
||||||
date DATE NOT NULL,
|
date DATE NOT NULL,
|
||||||
week_type week_type NOT NULL,
|
week_type week_type NOT NULL,
|
||||||
|
@ -153,8 +153,8 @@ CREATE TYPE substitution_type AS ENUM (
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE substitutions(
|
CREATE TABLE substitutions(
|
||||||
id SERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
substitution_query_id INTEGER NOT NULL REFERENCES substitution_queries(id),
|
substitution_query_id BIGINT NOT NULL REFERENCES substitution_queries(id),
|
||||||
subst_type substitution_type NOT NULL,
|
subst_type substitution_type NOT NULL,
|
||||||
lesson_id INTEGER NOT NULL,
|
lesson_id INTEGER NOT NULL,
|
||||||
start_time TIME NOT NULL,
|
start_time TIME NOT NULL,
|
||||||
|
@ -165,8 +165,8 @@ CREATE TABLE substitutions(
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE substitution_classes (
|
CREATE TABLE substitution_classes (
|
||||||
id SERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
substitution_id INTEGER NOT NULL REFERENCES substitutions(id),
|
substitution_id BIGINT NOT NULL REFERENCES substitutions(id),
|
||||||
position SMALLINT NOT NULL,
|
position SMALLINT NOT NULL,
|
||||||
class_id INTEGER NOT NULL REFERENCES classes(id),
|
class_id INTEGER NOT NULL REFERENCES classes(id),
|
||||||
original_id INTEGER REFERENCES classes(id),
|
original_id INTEGER REFERENCES classes(id),
|
||||||
|
@ -175,8 +175,8 @@ CREATE TABLE substitution_classes (
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE substitution_teachers (
|
CREATE TABLE substitution_teachers (
|
||||||
id SERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
substitution_id INTEGER NOT NULL REFERENCES substitutions(id),
|
substitution_id BIGINT NOT NULL REFERENCES substitutions(id),
|
||||||
position SMALLINT NOT NULL,
|
position SMALLINT NOT NULL,
|
||||||
teacher_id INTEGER REFERENCES teachers(id),
|
teacher_id INTEGER REFERENCES teachers(id),
|
||||||
original_id INTEGER REFERENCES teachers(id),
|
original_id INTEGER REFERENCES teachers(id),
|
||||||
|
@ -185,8 +185,8 @@ CREATE TABLE substitution_teachers (
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE substitution_subjects (
|
CREATE TABLE substitution_subjects (
|
||||||
id SERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
substitution_id INTEGER NOT NULL REFERENCES substitutions(id),
|
substitution_id BIGINT NOT NULL REFERENCES substitutions(id),
|
||||||
position SMALLINT NOT NULL,
|
position SMALLINT NOT NULL,
|
||||||
subject_id INTEGER NOT NULL REFERENCES subjects(id),
|
subject_id INTEGER NOT NULL REFERENCES subjects(id),
|
||||||
original_id INTEGER REFERENCES subjects(id),
|
original_id INTEGER REFERENCES subjects(id),
|
||||||
|
@ -195,8 +195,8 @@ CREATE TABLE substitution_subjects (
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE substitution_rooms (
|
CREATE TABLE substitution_rooms (
|
||||||
id SERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
substitution_id INTEGER NOT NULL REFERENCES substitutions(id),
|
substitution_id BIGINT NOT NULL REFERENCES substitutions(id),
|
||||||
position SMALLINT NOT NULL,
|
position SMALLINT NOT NULL,
|
||||||
room_id INTEGER REFERENCES rooms(id),
|
room_id INTEGER REFERENCES rooms(id),
|
||||||
original_id INTEGER REFERENCES rooms(id),
|
original_id INTEGER REFERENCES rooms(id),
|
||||||
|
|
|
@ -388,7 +388,7 @@ impl diesel::deserialize::FromSql<schema::sql_types::WeekType, diesel::pg::Pg> f
|
||||||
#[diesel(table_name = schema::substitution_queries)]
|
#[diesel(table_name = schema::substitution_queries)]
|
||||||
#[diesel(belongs_to(Schoolyear))]
|
#[diesel(belongs_to(Schoolyear))]
|
||||||
pub struct SubstitutionQuery {
|
pub struct SubstitutionQuery {
|
||||||
pub id: i32,
|
pub id: i64,
|
||||||
pub schoolyear_id: i32,
|
pub schoolyear_id: i32,
|
||||||
pub date: NaiveDate,
|
pub date: NaiveDate,
|
||||||
pub week_type: WeekType,
|
pub week_type: WeekType,
|
||||||
|
@ -508,8 +508,8 @@ impl From<untis::RpcSubstitionType> for SubstitutionType {
|
||||||
#[diesel(table_name = schema::substitutions)]
|
#[diesel(table_name = schema::substitutions)]
|
||||||
#[diesel(belongs_to(SubstitutionQuery))]
|
#[diesel(belongs_to(SubstitutionQuery))]
|
||||||
pub struct Substitution {
|
pub struct Substitution {
|
||||||
pub id: i32,
|
pub id: i64,
|
||||||
pub substitution_query_id: i32,
|
pub substitution_query_id: i64,
|
||||||
pub subst_type: SubstitutionType,
|
pub subst_type: SubstitutionType,
|
||||||
pub lesson_id: i32,
|
pub lesson_id: i32,
|
||||||
pub start_time: NaiveTime,
|
pub start_time: NaiveTime,
|
||||||
|
@ -522,7 +522,7 @@ pub struct Substitution {
|
||||||
#[derive(Insertable, Debug)]
|
#[derive(Insertable, Debug)]
|
||||||
#[diesel(table_name = schema::substitutions)]
|
#[diesel(table_name = schema::substitutions)]
|
||||||
pub struct NewSubstitution<'a> {
|
pub struct NewSubstitution<'a> {
|
||||||
pub substitution_query_id: i32,
|
pub substitution_query_id: i64,
|
||||||
pub subst_type: SubstitutionType,
|
pub subst_type: SubstitutionType,
|
||||||
pub lesson_id: i32,
|
pub lesson_id: i32,
|
||||||
pub start_time: NaiveTime,
|
pub start_time: NaiveTime,
|
||||||
|
@ -535,8 +535,8 @@ pub struct NewSubstitution<'a> {
|
||||||
#[diesel(belongs_to(Substitution))]
|
#[diesel(belongs_to(Substitution))]
|
||||||
#[diesel(belongs_to(Class))]
|
#[diesel(belongs_to(Class))]
|
||||||
pub struct SubstitutionClass {
|
pub struct SubstitutionClass {
|
||||||
pub id: i32,
|
pub id: i64,
|
||||||
pub substitution_id: i32,
|
pub substitution_id: i64,
|
||||||
pub position: i16,
|
pub position: i16,
|
||||||
pub class_id: i32,
|
pub class_id: i32,
|
||||||
pub original_id: Option<i32>,
|
pub original_id: Option<i32>,
|
||||||
|
@ -547,7 +547,7 @@ pub struct SubstitutionClass {
|
||||||
#[derive(Insertable, Debug)]
|
#[derive(Insertable, Debug)]
|
||||||
#[diesel(table_name = schema::substitution_classes)]
|
#[diesel(table_name = schema::substitution_classes)]
|
||||||
pub struct NewSubstitutionClass {
|
pub struct NewSubstitutionClass {
|
||||||
pub substitution_id: i32,
|
pub substitution_id: i64,
|
||||||
pub position: i16,
|
pub position: i16,
|
||||||
pub class_id: i32,
|
pub class_id: i32,
|
||||||
pub original_id: Option<i32>,
|
pub original_id: Option<i32>,
|
||||||
|
@ -558,8 +558,8 @@ pub struct NewSubstitutionClass {
|
||||||
#[diesel(belongs_to(Substitution))]
|
#[diesel(belongs_to(Substitution))]
|
||||||
#[diesel(belongs_to(Teacher))]
|
#[diesel(belongs_to(Teacher))]
|
||||||
pub struct SubstitutionTeacher {
|
pub struct SubstitutionTeacher {
|
||||||
pub id: i32,
|
pub id: i64,
|
||||||
pub substitution_id: i32,
|
pub substitution_id: i64,
|
||||||
pub position: i16,
|
pub position: i16,
|
||||||
pub teacher_id: Option<i32>,
|
pub teacher_id: Option<i32>,
|
||||||
pub original_id: Option<i32>,
|
pub original_id: Option<i32>,
|
||||||
|
@ -570,7 +570,7 @@ pub struct SubstitutionTeacher {
|
||||||
#[derive(Insertable, Debug)]
|
#[derive(Insertable, Debug)]
|
||||||
#[diesel(table_name = schema::substitution_teachers)]
|
#[diesel(table_name = schema::substitution_teachers)]
|
||||||
pub struct NewSubstitutionTeacher {
|
pub struct NewSubstitutionTeacher {
|
||||||
pub substitution_id: i32,
|
pub substitution_id: i64,
|
||||||
pub position: i16,
|
pub position: i16,
|
||||||
pub teacher_id: Option<i32>,
|
pub teacher_id: Option<i32>,
|
||||||
pub original_id: Option<i32>,
|
pub original_id: Option<i32>,
|
||||||
|
@ -581,8 +581,8 @@ pub struct NewSubstitutionTeacher {
|
||||||
#[diesel(belongs_to(Substitution))]
|
#[diesel(belongs_to(Substitution))]
|
||||||
#[diesel(belongs_to(Subject))]
|
#[diesel(belongs_to(Subject))]
|
||||||
pub struct SubstitutionSubject {
|
pub struct SubstitutionSubject {
|
||||||
pub id: i32,
|
pub id: i64,
|
||||||
pub substitution_id: i32,
|
pub substitution_id: i64,
|
||||||
pub position: i16,
|
pub position: i16,
|
||||||
pub subject_id: i32,
|
pub subject_id: i32,
|
||||||
pub original_id: Option<i32>,
|
pub original_id: Option<i32>,
|
||||||
|
@ -593,7 +593,7 @@ pub struct SubstitutionSubject {
|
||||||
#[derive(Insertable, Debug)]
|
#[derive(Insertable, Debug)]
|
||||||
#[diesel(table_name = schema::substitution_subjects)]
|
#[diesel(table_name = schema::substitution_subjects)]
|
||||||
pub struct NewSubstitutionSubject {
|
pub struct NewSubstitutionSubject {
|
||||||
pub substitution_id: i32,
|
pub substitution_id: i64,
|
||||||
pub position: i16,
|
pub position: i16,
|
||||||
pub subject_id: i32,
|
pub subject_id: i32,
|
||||||
pub original_id: Option<i32>,
|
pub original_id: Option<i32>,
|
||||||
|
@ -604,8 +604,8 @@ pub struct NewSubstitutionSubject {
|
||||||
#[diesel(belongs_to(Substitution))]
|
#[diesel(belongs_to(Substitution))]
|
||||||
#[diesel(belongs_to(Room))]
|
#[diesel(belongs_to(Room))]
|
||||||
pub struct SubstitutionRoom {
|
pub struct SubstitutionRoom {
|
||||||
pub id: i32,
|
pub id: i64,
|
||||||
pub substitution_id: i32,
|
pub substitution_id: i64,
|
||||||
pub position: i16,
|
pub position: i16,
|
||||||
pub room_id: Option<i32>,
|
pub room_id: Option<i32>,
|
||||||
pub original_id: Option<i32>,
|
pub original_id: Option<i32>,
|
||||||
|
@ -616,7 +616,7 @@ pub struct SubstitutionRoom {
|
||||||
#[derive(Insertable, Debug)]
|
#[derive(Insertable, Debug)]
|
||||||
#[diesel(table_name = schema::substitution_rooms)]
|
#[diesel(table_name = schema::substitution_rooms)]
|
||||||
pub struct NewSubstitutionRoom {
|
pub struct NewSubstitutionRoom {
|
||||||
pub substitution_id: i32,
|
pub substitution_id: i64,
|
||||||
pub position: i16,
|
pub position: i16,
|
||||||
pub room_id: Option<i32>,
|
pub room_id: Option<i32>,
|
||||||
pub original_id: Option<i32>,
|
pub original_id: Option<i32>,
|
||||||
|
|
|
@ -152,7 +152,7 @@ diesel::table! {
|
||||||
use super::sql_types::*;
|
use super::sql_types::*;
|
||||||
|
|
||||||
substitution_queries {
|
substitution_queries {
|
||||||
id -> Integer,
|
id -> BigInt,
|
||||||
schoolyear_id -> Integer,
|
schoolyear_id -> Integer,
|
||||||
date -> Date,
|
date -> Date,
|
||||||
week_type -> WeekType,
|
week_type -> WeekType,
|
||||||
|
@ -168,8 +168,8 @@ diesel::table! {
|
||||||
use super::sql_types::*;
|
use super::sql_types::*;
|
||||||
|
|
||||||
substitutions {
|
substitutions {
|
||||||
id -> Integer,
|
id -> BigInt,
|
||||||
substitution_query_id -> Integer,
|
substitution_query_id -> BigInt,
|
||||||
subst_type -> SubstitutionType,
|
subst_type -> SubstitutionType,
|
||||||
lesson_id -> Integer,
|
lesson_id -> Integer,
|
||||||
start_time -> Time,
|
start_time -> Time,
|
||||||
|
@ -182,8 +182,8 @@ diesel::table! {
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
substitution_classes {
|
substitution_classes {
|
||||||
id -> Integer,
|
id -> BigInt,
|
||||||
substitution_id -> Integer,
|
substitution_id -> BigInt,
|
||||||
position -> SmallInt,
|
position -> SmallInt,
|
||||||
class_id -> Integer,
|
class_id -> Integer,
|
||||||
original_id -> Nullable<Integer>,
|
original_id -> Nullable<Integer>,
|
||||||
|
@ -194,8 +194,8 @@ diesel::table! {
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
substitution_teachers {
|
substitution_teachers {
|
||||||
id -> Integer,
|
id -> BigInt,
|
||||||
substitution_id -> Integer,
|
substitution_id -> BigInt,
|
||||||
position -> SmallInt,
|
position -> SmallInt,
|
||||||
teacher_id -> Nullable<Integer>,
|
teacher_id -> Nullable<Integer>,
|
||||||
original_id -> Nullable<Integer>,
|
original_id -> Nullable<Integer>,
|
||||||
|
@ -206,8 +206,8 @@ diesel::table! {
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
substitution_subjects {
|
substitution_subjects {
|
||||||
id -> Integer,
|
id -> BigInt,
|
||||||
substitution_id -> Integer,
|
substitution_id -> BigInt,
|
||||||
position -> SmallInt,
|
position -> SmallInt,
|
||||||
subject_id -> Integer,
|
subject_id -> Integer,
|
||||||
original_id -> Nullable<Integer>,
|
original_id -> Nullable<Integer>,
|
||||||
|
@ -218,8 +218,8 @@ diesel::table! {
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
substitution_rooms {
|
substitution_rooms {
|
||||||
id -> Integer,
|
id -> BigInt,
|
||||||
substitution_id -> Integer,
|
substitution_id -> BigInt,
|
||||||
position -> SmallInt,
|
position -> SmallInt,
|
||||||
room_id -> Nullable<Integer>,
|
room_id -> Nullable<Integer>,
|
||||||
original_id -> Nullable<Integer>,
|
original_id -> Nullable<Integer>,
|
||||||
|
|
89
bvplan/src/worker/cleanup.rs
Normal file
89
bvplan/src/worker/cleanup.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use celery::{error::TaskError, task::TaskResult};
|
||||||
|
use chrono::prelude::*;
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
use crate::db;
|
||||||
|
|
||||||
|
fn do_cleanup(db_conn: &mut db::Connection) -> Result<()> {
|
||||||
|
let timegrid_ids = db::schema::timegrids::table
|
||||||
|
.select(db::schema::timegrids::id)
|
||||||
|
.filter(db::schema::timegrids::active.eq(false))
|
||||||
|
.load::<i32>(db_conn)?;
|
||||||
|
let timegrid_day_ids = db::schema::timegrid_days::table
|
||||||
|
.select(db::schema::timegrid_days::id)
|
||||||
|
.filter(db::schema::timegrid_days::timegrid_id.eq_any(&timegrid_ids))
|
||||||
|
.load::<i32>(db_conn)?;
|
||||||
|
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::timegrid_time_unit::table
|
||||||
|
.filter(db::schema::timegrid_time_unit::timegrid_day_id.eq_any(&timegrid_day_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::timegrid_days::table
|
||||||
|
.filter(db::schema::timegrid_days::id.eq_any(timegrid_day_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::timegrids::table.filter(db::schema::timegrids::id.eq_any(timegrid_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
|
||||||
|
let subst_query_ids = db::schema::substitution_queries::table
|
||||||
|
.select(db::schema::substitution_queries::id)
|
||||||
|
.filter(
|
||||||
|
db::schema::substitution_queries::queried_at
|
||||||
|
.lt(Local::now().naive_local() - chrono::Duration::hours(1)),
|
||||||
|
)
|
||||||
|
.load::<i64>(db_conn)?;
|
||||||
|
let subst_ids = db::schema::substitutions::table
|
||||||
|
.select(db::schema::substitutions::id)
|
||||||
|
.filter(db::schema::substitutions::substitution_query_id.eq_any(&subst_query_ids))
|
||||||
|
.load::<i64>(db_conn)?;
|
||||||
|
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::substitution_classes::table
|
||||||
|
.filter(db::schema::substitution_classes::substitution_id.eq_any(&subst_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::substitution_teachers::table
|
||||||
|
.filter(db::schema::substitution_teachers::substitution_id.eq_any(&subst_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::substitution_subjects::table
|
||||||
|
.filter(db::schema::substitution_subjects::substitution_id.eq_any(&subst_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::substitution_rooms::table
|
||||||
|
.filter(db::schema::substitution_rooms::substitution_id.eq_any(&subst_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::substitutions::table.filter(db::schema::substitutions::id.eq_any(subst_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::delete(
|
||||||
|
db::schema::substitution_queries::table
|
||||||
|
.filter(db::schema::substitution_queries::id.eq_any(subst_query_ids)),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[celery::task]
|
||||||
|
pub async fn cleanup() -> TaskResult<()> {
|
||||||
|
let db_conn = &mut match db::POOL.get() {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
||||||
|
};
|
||||||
|
if let Err(e) = do_cleanup(db_conn) {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -25,286 +25,11 @@ async fn get_schoolyear(client: &untis::Client, db_conn: &mut db::Connection) ->
|
||||||
.first(db_conn)?)
|
.first(db_conn)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_current_tenant(
|
|
||||||
client: &untis::Client,
|
|
||||||
db_conn: &mut PgConnection,
|
|
||||||
schoolyear_id: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let tenant = client.current_tenant().await?;
|
|
||||||
if diesel::select(diesel::dsl::not(diesel::dsl::exists(
|
|
||||||
db::schema::tenants::table.filter(db::schema::tenants::untis_id.eq(tenant.id)),
|
|
||||||
)))
|
|
||||||
.get_result::<bool>(db_conn)?
|
|
||||||
{
|
|
||||||
diesel::update(db::schema::tenants::table)
|
|
||||||
.filter(db::schema::tenants::active)
|
|
||||||
.set(db::schema::tenants::active.eq(false))
|
|
||||||
.execute(db_conn)?;
|
|
||||||
diesel::insert_into(db::schema::tenants::table)
|
|
||||||
.values(db::models::NewTenant {
|
|
||||||
untis_id: tenant.id,
|
|
||||||
schoolyear_id,
|
|
||||||
name: &tenant.display_name,
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
.execute(db_conn)?;
|
|
||||||
} else if diesel::select(diesel::dsl::exists(
|
|
||||||
db::schema::tenants::table
|
|
||||||
.filter(db::schema::tenants::untis_id.eq(tenant.id))
|
|
||||||
.filter(db::schema::tenants::active.eq(false)),
|
|
||||||
))
|
|
||||||
.get_result::<bool>(db_conn)?
|
|
||||||
{
|
|
||||||
diesel::update(db::schema::tenants::table)
|
|
||||||
.filter(db::schema::tenants::active)
|
|
||||||
.set((
|
|
||||||
db::schema::tenants::active.eq(false),
|
|
||||||
db::schema::tenants::updated_at.eq(diesel::dsl::now),
|
|
||||||
))
|
|
||||||
.execute(db_conn)?;
|
|
||||||
diesel::update(db::schema::tenants::table)
|
|
||||||
.filter(db::schema::tenants::untis_id.eq(tenant.id))
|
|
||||||
.set((
|
|
||||||
db::schema::tenants::active.eq(true),
|
|
||||||
db::schema::tenants::updated_at.eq(diesel::dsl::now),
|
|
||||||
))
|
|
||||||
.execute(db_conn)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_timegrid(
|
|
||||||
client: &untis::Client,
|
|
||||||
db_conn: &mut PgConnection,
|
|
||||||
schoolyear_id: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let days = client.timegrid().await?;
|
|
||||||
|
|
||||||
diesel::update(db::schema::timegrids::table)
|
|
||||||
.filter(db::schema::timegrids::active)
|
|
||||||
.set(db::schema::timegrids::active.eq(false))
|
|
||||||
.execute(db_conn)?;
|
|
||||||
let timegrid_id = diesel::insert_into(db::schema::timegrids::table)
|
|
||||||
.values(db::models::NewTimegrid {
|
|
||||||
schoolyear_id,
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
.returning(db::schema::timegrids::id)
|
|
||||||
.get_result::<i32>(db_conn)?;
|
|
||||||
|
|
||||||
for day in days {
|
|
||||||
let timegrid_day_id = diesel::insert_into(db::schema::timegrid_days::table)
|
|
||||||
.values(db::models::NewTimegridDay {
|
|
||||||
timegrid_id,
|
|
||||||
weekday: day.day.try_into()?,
|
|
||||||
})
|
|
||||||
.returning(db::schema::timegrid_days::id)
|
|
||||||
.get_result::<i32>(db_conn)?;
|
|
||||||
diesel::insert_into(db::schema::timegrid_time_unit::table)
|
|
||||||
.values(
|
|
||||||
day.time_units
|
|
||||||
.into_iter()
|
|
||||||
.map(|x| db::models::NewTimegridTimeUnit {
|
|
||||||
timegrid_day_id,
|
|
||||||
start_time: x.start_time,
|
|
||||||
end_time: x.end_time,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
)
|
|
||||||
.execute(db_conn)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_teachers(
|
|
||||||
client: &untis::Client,
|
|
||||||
db_conn: &mut PgConnection,
|
|
||||||
schoolyear_id: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let existing_teachers = db::schema::teachers::table
|
|
||||||
.select(db::schema::teachers::untis_id)
|
|
||||||
.filter(db::schema::teachers::schoolyear_id.eq(schoolyear_id))
|
|
||||||
.load::<i32>(db_conn)?;
|
|
||||||
diesel::insert_into(db::schema::teachers::table)
|
|
||||||
.values(
|
|
||||||
&client
|
|
||||||
.teachers()
|
|
||||||
.await?
|
|
||||||
.iter()
|
|
||||||
.filter(|t| !existing_teachers.contains(&t.id))
|
|
||||||
.map(|t| db::models::NewTeacher {
|
|
||||||
untis_id: t.id,
|
|
||||||
schoolyear_id,
|
|
||||||
name: &t.name,
|
|
||||||
forename: if t.forename.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(&t.forename)
|
|
||||||
},
|
|
||||||
display_name: &t.display_name,
|
|
||||||
})
|
|
||||||
.collect::<Vec<db::models::NewTeacher>>(),
|
|
||||||
)
|
|
||||||
.execute(db_conn)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_classes(
|
|
||||||
client: &untis::Client,
|
|
||||||
db_conn: &mut PgConnection,
|
|
||||||
schoolyear_id: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let existing_classes = db::schema::classes::table
|
|
||||||
.select(db::schema::classes::untis_id)
|
|
||||||
.filter(db::schema::classes::schoolyear_id.eq(schoolyear_id))
|
|
||||||
.load::<i32>(db_conn)?;
|
|
||||||
diesel::insert_into(db::schema::classes::table)
|
|
||||||
.values(
|
|
||||||
&client
|
|
||||||
.classes()
|
|
||||||
.await?
|
|
||||||
.iter()
|
|
||||||
.filter(|c| !existing_classes.contains(&c.id))
|
|
||||||
.map(|c| db::models::NewClass {
|
|
||||||
untis_id: c.id,
|
|
||||||
schoolyear_id,
|
|
||||||
name: &c.name,
|
|
||||||
long_name: &c.long_name,
|
|
||||||
active: c.active,
|
|
||||||
})
|
|
||||||
.collect::<Vec<db::models::NewClass>>(),
|
|
||||||
)
|
|
||||||
.execute(db_conn)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_subjects(
|
|
||||||
client: &untis::Client,
|
|
||||||
db_conn: &mut PgConnection,
|
|
||||||
schoolyear_id: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let existing_classes = db::schema::subjects::table
|
|
||||||
.select(db::schema::subjects::untis_id)
|
|
||||||
.filter(db::schema::subjects::schoolyear_id.eq(schoolyear_id))
|
|
||||||
.load::<i32>(db_conn)?;
|
|
||||||
diesel::insert_into(db::schema::subjects::table)
|
|
||||||
.values(
|
|
||||||
&client
|
|
||||||
.subjects()
|
|
||||||
.await?
|
|
||||||
.iter()
|
|
||||||
.filter(|c| !existing_classes.contains(&c.id))
|
|
||||||
.map(|c| db::models::NewSubject {
|
|
||||||
untis_id: c.id,
|
|
||||||
schoolyear_id,
|
|
||||||
name: &c.name,
|
|
||||||
long_name: &c.long_name,
|
|
||||||
})
|
|
||||||
.collect::<Vec<db::models::NewSubject>>(),
|
|
||||||
)
|
|
||||||
.execute(db_conn)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_rooms(
|
|
||||||
client: &untis::Client,
|
|
||||||
db_conn: &mut PgConnection,
|
|
||||||
schoolyear_id: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let existing_classes = db::schema::rooms::table
|
|
||||||
.select(db::schema::rooms::untis_id)
|
|
||||||
.filter(db::schema::rooms::schoolyear_id.eq(schoolyear_id))
|
|
||||||
.load::<i32>(db_conn)?;
|
|
||||||
diesel::insert_into(db::schema::rooms::table)
|
|
||||||
.values(
|
|
||||||
&client
|
|
||||||
.rooms()
|
|
||||||
.await?
|
|
||||||
.iter()
|
|
||||||
.filter(|c| !existing_classes.contains(&c.id))
|
|
||||||
.map(|c| db::models::NewRoom {
|
|
||||||
untis_id: c.id,
|
|
||||||
schoolyear_id,
|
|
||||||
name: &c.name,
|
|
||||||
long_name: &c.long_name,
|
|
||||||
})
|
|
||||||
.collect::<Vec<db::models::NewRoom>>(),
|
|
||||||
)
|
|
||||||
.execute(db_conn)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_departments(
|
|
||||||
client: &untis::Client,
|
|
||||||
db_conn: &mut PgConnection,
|
|
||||||
schoolyear_id: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let existing_classes = db::schema::departments::table
|
|
||||||
.select(db::schema::departments::untis_id)
|
|
||||||
.filter(db::schema::departments::schoolyear_id.eq(schoolyear_id))
|
|
||||||
.load::<i32>(db_conn)?;
|
|
||||||
diesel::insert_into(db::schema::departments::table)
|
|
||||||
.values(
|
|
||||||
&client
|
|
||||||
.departments()
|
|
||||||
.await?
|
|
||||||
.iter()
|
|
||||||
.filter(|c| !existing_classes.contains(&c.id))
|
|
||||||
.map(|c| db::models::NewDepartment {
|
|
||||||
untis_id: c.id,
|
|
||||||
schoolyear_id,
|
|
||||||
name: &c.name,
|
|
||||||
long_name: &c.long_name,
|
|
||||||
})
|
|
||||||
.collect::<Vec<db::models::NewDepartment>>(),
|
|
||||||
)
|
|
||||||
.execute(db_conn)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_holidays(
|
|
||||||
client: &untis::Client,
|
|
||||||
db_conn: &mut PgConnection,
|
|
||||||
schoolyear_id: i32,
|
|
||||||
) -> Result<()> {
|
|
||||||
let existing_classes = db::schema::holidays::table
|
|
||||||
.select(db::schema::holidays::untis_id)
|
|
||||||
.filter(db::schema::holidays::schoolyear_id.eq(schoolyear_id))
|
|
||||||
.load::<i32>(db_conn)?;
|
|
||||||
diesel::insert_into(db::schema::holidays::table)
|
|
||||||
.values(
|
|
||||||
&client
|
|
||||||
.holidays()
|
|
||||||
.await?
|
|
||||||
.iter()
|
|
||||||
.filter(|c| !existing_classes.contains(&c.id))
|
|
||||||
.map(|c| db::models::NewHoliday {
|
|
||||||
untis_id: c.id,
|
|
||||||
schoolyear_id,
|
|
||||||
name: &c.name,
|
|
||||||
long_name: &c.long_name,
|
|
||||||
start_date: c.start_date,
|
|
||||||
end_date: c.end_date,
|
|
||||||
})
|
|
||||||
.collect::<Vec<db::models::NewHoliday>>(),
|
|
||||||
)
|
|
||||||
.execute(db_conn)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn fetch_substitutions(
|
async fn fetch_substitutions(
|
||||||
client: &untis::Client,
|
client: &untis::Client,
|
||||||
db_conn: &mut PgConnection,
|
db_conn: &mut db::Connection,
|
||||||
schoolyear_id: i32,
|
schoolyear_id: i32,
|
||||||
) -> Result<i32> {
|
) -> Result<i64> {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref TITLE_SELECTOR: scraper::Selector =
|
static ref TITLE_SELECTOR: scraper::Selector =
|
||||||
scraper::Selector::parse(".mon_title").unwrap();
|
scraper::Selector::parse(".mon_title").unwrap();
|
||||||
|
@ -362,7 +87,7 @@ async fn fetch_substitutions(
|
||||||
queried_at: Utc::now().naive_utc(),
|
queried_at: Utc::now().naive_utc(),
|
||||||
})
|
})
|
||||||
.returning(db::schema::substitution_queries::id)
|
.returning(db::schema::substitution_queries::id)
|
||||||
.get_result::<i32>(db_conn)?;
|
.get_result::<i64>(db_conn)?;
|
||||||
|
|
||||||
for substitution in client.substitutions(&date, &date, None).await? {
|
for substitution in client.substitutions(&date, &date, None).await? {
|
||||||
let substitution_id = diesel::insert_into(db::schema::substitutions::table)
|
let substitution_id = diesel::insert_into(db::schema::substitutions::table)
|
||||||
|
@ -375,7 +100,7 @@ async fn fetch_substitutions(
|
||||||
text: substitution.text.as_deref(),
|
text: substitution.text.as_deref(),
|
||||||
})
|
})
|
||||||
.returning(db::schema::substitutions::id)
|
.returning(db::schema::substitutions::id)
|
||||||
.get_result::<i32>(db_conn)?;
|
.get_result::<i64>(db_conn)?;
|
||||||
|
|
||||||
diesel::insert_into(db::schema::substitution_classes::table)
|
diesel::insert_into(db::schema::substitution_classes::table)
|
||||||
.values(
|
.values(
|
||||||
|
@ -525,7 +250,7 @@ fn get_period(times: &Vec<StartEndTime>, start: bool, time: NaiveTime) -> Option
|
||||||
fn cache_substitutions(
|
fn cache_substitutions(
|
||||||
db_conn: &mut PgConnection,
|
db_conn: &mut PgConnection,
|
||||||
redis_conn: &mut cache::Connection,
|
redis_conn: &mut cache::Connection,
|
||||||
substitution_query_id: i32,
|
substitution_query_id: i64,
|
||||||
last_import_time: NaiveDateTime,
|
last_import_time: NaiveDateTime,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let (queried_at, date, week_type) = db::schema::substitution_queries::table
|
let (queried_at, date, week_type) = db::schema::substitution_queries::table
|
||||||
|
@ -717,7 +442,7 @@ fn cache_substitutions(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[celery::task]
|
#[celery::task]
|
||||||
pub async fn update_info() -> TaskResult<()> {
|
pub async fn get_substitutions() -> TaskResult<()> {
|
||||||
let dur = Duration::from_secs(2);
|
let dur = Duration::from_secs(2);
|
||||||
|
|
||||||
thread::sleep(dur);
|
thread::sleep(dur);
|
||||||
|
@ -744,38 +469,6 @@ pub async fn update_info() -> TaskResult<()> {
|
||||||
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
||||||
};
|
};
|
||||||
thread::sleep(dur);
|
thread::sleep(dur);
|
||||||
if let Err(e) = fetch_current_tenant(&client, db_conn, schoolyear_id).await {
|
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
thread::sleep(dur);
|
|
||||||
if let Err(e) = fetch_timegrid(&client, db_conn, schoolyear_id).await {
|
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
thread::sleep(dur);
|
|
||||||
if let Err(e) = fetch_teachers(&client, db_conn, schoolyear_id).await {
|
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
thread::sleep(dur);
|
|
||||||
if let Err(e) = fetch_classes(&client, db_conn, schoolyear_id).await {
|
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
thread::sleep(dur);
|
|
||||||
if let Err(e) = fetch_subjects(&client, db_conn, schoolyear_id).await {
|
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
thread::sleep(dur);
|
|
||||||
if let Err(e) = fetch_rooms(&client, db_conn, schoolyear_id).await {
|
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
thread::sleep(dur);
|
|
||||||
if let Err(e) = fetch_departments(&client, db_conn, schoolyear_id).await {
|
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
thread::sleep(dur);
|
|
||||||
if let Err(e) = fetch_holidays(&client, db_conn, schoolyear_id).await {
|
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
|
||||||
}
|
|
||||||
thread::sleep(dur);
|
|
||||||
let last_import_time = match client.last_import_time().await {
|
let last_import_time = match client.last_import_time().await {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
|
@ -7,7 +7,8 @@ use stdext::duration::DurationExt;
|
||||||
|
|
||||||
use crate::config;
|
use crate::config;
|
||||||
|
|
||||||
pub mod update_info;
|
pub mod cleanup;
|
||||||
|
pub mod get_substitutions;
|
||||||
pub mod update_meta;
|
pub mod update_meta;
|
||||||
|
|
||||||
pub const QUEUE_NAME: &str = "celery";
|
pub const QUEUE_NAME: &str = "celery";
|
||||||
|
@ -22,8 +23,9 @@ pub async fn init() {
|
||||||
celery::app!(
|
celery::app!(
|
||||||
broker = AMQPBroker { &config::CONFIG.amqp_url },
|
broker = AMQPBroker { &config::CONFIG.amqp_url },
|
||||||
tasks = [
|
tasks = [
|
||||||
update_info::update_info,
|
get_substitutions::get_substitutions,
|
||||||
update_meta::update_meta,
|
update_meta::update_meta,
|
||||||
|
cleanup::cleanup,
|
||||||
],
|
],
|
||||||
task_routes = [
|
task_routes = [
|
||||||
"*" => QUEUE_NAME,
|
"*" => QUEUE_NAME,
|
||||||
|
@ -45,15 +47,20 @@ pub fn beat() -> impl std::future::Future<
|
||||||
celery::beat!(
|
celery::beat!(
|
||||||
broker = AMQPBroker { &config::CONFIG.amqp_url },
|
broker = AMQPBroker { &config::CONFIG.amqp_url },
|
||||||
tasks = [
|
tasks = [
|
||||||
"update_info" => {
|
"get_substitutions" => {
|
||||||
update_info::update_info,
|
get_substitutions::get_substitutions,
|
||||||
schedule = DeltaSchedule::new(Duration::from_minutes(999)),
|
schedule = DeltaSchedule::new(Duration::from_minutes(5)),
|
||||||
args = (),
|
args = (),
|
||||||
},
|
},
|
||||||
"update_meta" => {
|
"update_meta" => {
|
||||||
update_meta::update_meta,
|
update_meta::update_meta,
|
||||||
schedule = DeltaSchedule::new(Duration::from_hours(6)),
|
schedule = DeltaSchedule::new(Duration::from_hours(6)),
|
||||||
args = (),
|
args = (),
|
||||||
|
},
|
||||||
|
"cleanup" => {
|
||||||
|
cleanup::cleanup,
|
||||||
|
schedule = DeltaSchedule::new(Duration::from_hours(1)),
|
||||||
|
args = (),
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
task_routes = [
|
task_routes = [
|
||||||
|
|
|
@ -43,6 +43,281 @@ async fn fetch_schoolyears(client: &untis::Client, db_conn: &mut db::Connection)
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn fetch_current_tenant(
|
||||||
|
client: &untis::Client,
|
||||||
|
db_conn: &mut PgConnection,
|
||||||
|
schoolyear_id: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let tenant = client.current_tenant().await?;
|
||||||
|
if diesel::select(diesel::dsl::not(diesel::dsl::exists(
|
||||||
|
db::schema::tenants::table.filter(db::schema::tenants::untis_id.eq(tenant.id)),
|
||||||
|
)))
|
||||||
|
.get_result::<bool>(db_conn)?
|
||||||
|
{
|
||||||
|
diesel::update(db::schema::tenants::table)
|
||||||
|
.filter(db::schema::tenants::active)
|
||||||
|
.set(db::schema::tenants::active.eq(false))
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::insert_into(db::schema::tenants::table)
|
||||||
|
.values(db::models::NewTenant {
|
||||||
|
untis_id: tenant.id,
|
||||||
|
schoolyear_id,
|
||||||
|
name: &tenant.display_name,
|
||||||
|
active: true,
|
||||||
|
})
|
||||||
|
.execute(db_conn)?;
|
||||||
|
} else if diesel::select(diesel::dsl::exists(
|
||||||
|
db::schema::tenants::table
|
||||||
|
.filter(db::schema::tenants::untis_id.eq(tenant.id))
|
||||||
|
.filter(db::schema::tenants::active.eq(false)),
|
||||||
|
))
|
||||||
|
.get_result::<bool>(db_conn)?
|
||||||
|
{
|
||||||
|
diesel::update(db::schema::tenants::table)
|
||||||
|
.filter(db::schema::tenants::active)
|
||||||
|
.set((
|
||||||
|
db::schema::tenants::active.eq(false),
|
||||||
|
db::schema::tenants::updated_at.eq(diesel::dsl::now),
|
||||||
|
))
|
||||||
|
.execute(db_conn)?;
|
||||||
|
diesel::update(db::schema::tenants::table)
|
||||||
|
.filter(db::schema::tenants::untis_id.eq(tenant.id))
|
||||||
|
.set((
|
||||||
|
db::schema::tenants::active.eq(true),
|
||||||
|
db::schema::tenants::updated_at.eq(diesel::dsl::now),
|
||||||
|
))
|
||||||
|
.execute(db_conn)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_timegrid(
|
||||||
|
client: &untis::Client,
|
||||||
|
db_conn: &mut PgConnection,
|
||||||
|
schoolyear_id: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let days = client.timegrid().await?;
|
||||||
|
|
||||||
|
diesel::update(db::schema::timegrids::table)
|
||||||
|
.filter(db::schema::timegrids::active)
|
||||||
|
.set(db::schema::timegrids::active.eq(false))
|
||||||
|
.execute(db_conn)?;
|
||||||
|
let timegrid_id = diesel::insert_into(db::schema::timegrids::table)
|
||||||
|
.values(db::models::NewTimegrid {
|
||||||
|
schoolyear_id,
|
||||||
|
active: true,
|
||||||
|
})
|
||||||
|
.returning(db::schema::timegrids::id)
|
||||||
|
.get_result::<i32>(db_conn)?;
|
||||||
|
|
||||||
|
for day in days {
|
||||||
|
let timegrid_day_id = diesel::insert_into(db::schema::timegrid_days::table)
|
||||||
|
.values(db::models::NewTimegridDay {
|
||||||
|
timegrid_id,
|
||||||
|
weekday: day.day.try_into()?,
|
||||||
|
})
|
||||||
|
.returning(db::schema::timegrid_days::id)
|
||||||
|
.get_result::<i32>(db_conn)?;
|
||||||
|
diesel::insert_into(db::schema::timegrid_time_unit::table)
|
||||||
|
.values(
|
||||||
|
day.time_units
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| db::models::NewTimegridTimeUnit {
|
||||||
|
timegrid_day_id,
|
||||||
|
start_time: x.start_time,
|
||||||
|
end_time: x.end_time,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_teachers(
|
||||||
|
client: &untis::Client,
|
||||||
|
db_conn: &mut PgConnection,
|
||||||
|
schoolyear_id: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let existing_teachers = db::schema::teachers::table
|
||||||
|
.select(db::schema::teachers::untis_id)
|
||||||
|
.filter(db::schema::teachers::schoolyear_id.eq(schoolyear_id))
|
||||||
|
.load::<i32>(db_conn)?;
|
||||||
|
diesel::insert_into(db::schema::teachers::table)
|
||||||
|
.values(
|
||||||
|
&client
|
||||||
|
.teachers()
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.filter(|t| !existing_teachers.contains(&t.id))
|
||||||
|
.map(|t| db::models::NewTeacher {
|
||||||
|
untis_id: t.id,
|
||||||
|
schoolyear_id,
|
||||||
|
name: &t.name,
|
||||||
|
forename: if t.forename.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(&t.forename)
|
||||||
|
},
|
||||||
|
display_name: &t.display_name,
|
||||||
|
})
|
||||||
|
.collect::<Vec<db::models::NewTeacher>>(),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_classes(
|
||||||
|
client: &untis::Client,
|
||||||
|
db_conn: &mut PgConnection,
|
||||||
|
schoolyear_id: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let existing_classes = db::schema::classes::table
|
||||||
|
.select(db::schema::classes::untis_id)
|
||||||
|
.filter(db::schema::classes::schoolyear_id.eq(schoolyear_id))
|
||||||
|
.load::<i32>(db_conn)?;
|
||||||
|
diesel::insert_into(db::schema::classes::table)
|
||||||
|
.values(
|
||||||
|
&client
|
||||||
|
.classes()
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.filter(|c| !existing_classes.contains(&c.id))
|
||||||
|
.map(|c| db::models::NewClass {
|
||||||
|
untis_id: c.id,
|
||||||
|
schoolyear_id,
|
||||||
|
name: &c.name,
|
||||||
|
long_name: &c.long_name,
|
||||||
|
active: c.active,
|
||||||
|
})
|
||||||
|
.collect::<Vec<db::models::NewClass>>(),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_subjects(
|
||||||
|
client: &untis::Client,
|
||||||
|
db_conn: &mut PgConnection,
|
||||||
|
schoolyear_id: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let existing_classes = db::schema::subjects::table
|
||||||
|
.select(db::schema::subjects::untis_id)
|
||||||
|
.filter(db::schema::subjects::schoolyear_id.eq(schoolyear_id))
|
||||||
|
.load::<i32>(db_conn)?;
|
||||||
|
diesel::insert_into(db::schema::subjects::table)
|
||||||
|
.values(
|
||||||
|
&client
|
||||||
|
.subjects()
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.filter(|c| !existing_classes.contains(&c.id))
|
||||||
|
.map(|c| db::models::NewSubject {
|
||||||
|
untis_id: c.id,
|
||||||
|
schoolyear_id,
|
||||||
|
name: &c.name,
|
||||||
|
long_name: &c.long_name,
|
||||||
|
})
|
||||||
|
.collect::<Vec<db::models::NewSubject>>(),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_rooms(
|
||||||
|
client: &untis::Client,
|
||||||
|
db_conn: &mut PgConnection,
|
||||||
|
schoolyear_id: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let existing_classes = db::schema::rooms::table
|
||||||
|
.select(db::schema::rooms::untis_id)
|
||||||
|
.filter(db::schema::rooms::schoolyear_id.eq(schoolyear_id))
|
||||||
|
.load::<i32>(db_conn)?;
|
||||||
|
diesel::insert_into(db::schema::rooms::table)
|
||||||
|
.values(
|
||||||
|
&client
|
||||||
|
.rooms()
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.filter(|c| !existing_classes.contains(&c.id))
|
||||||
|
.map(|c| db::models::NewRoom {
|
||||||
|
untis_id: c.id,
|
||||||
|
schoolyear_id,
|
||||||
|
name: &c.name,
|
||||||
|
long_name: &c.long_name,
|
||||||
|
})
|
||||||
|
.collect::<Vec<db::models::NewRoom>>(),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_departments(
|
||||||
|
client: &untis::Client,
|
||||||
|
db_conn: &mut PgConnection,
|
||||||
|
schoolyear_id: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let existing_classes = db::schema::departments::table
|
||||||
|
.select(db::schema::departments::untis_id)
|
||||||
|
.filter(db::schema::departments::schoolyear_id.eq(schoolyear_id))
|
||||||
|
.load::<i32>(db_conn)?;
|
||||||
|
diesel::insert_into(db::schema::departments::table)
|
||||||
|
.values(
|
||||||
|
&client
|
||||||
|
.departments()
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.filter(|c| !existing_classes.contains(&c.id))
|
||||||
|
.map(|c| db::models::NewDepartment {
|
||||||
|
untis_id: c.id,
|
||||||
|
schoolyear_id,
|
||||||
|
name: &c.name,
|
||||||
|
long_name: &c.long_name,
|
||||||
|
})
|
||||||
|
.collect::<Vec<db::models::NewDepartment>>(),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_holidays(
|
||||||
|
client: &untis::Client,
|
||||||
|
db_conn: &mut PgConnection,
|
||||||
|
schoolyear_id: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let existing_classes = db::schema::holidays::table
|
||||||
|
.select(db::schema::holidays::untis_id)
|
||||||
|
.filter(db::schema::holidays::schoolyear_id.eq(schoolyear_id))
|
||||||
|
.load::<i32>(db_conn)?;
|
||||||
|
diesel::insert_into(db::schema::holidays::table)
|
||||||
|
.values(
|
||||||
|
&client
|
||||||
|
.holidays()
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.filter(|c| !existing_classes.contains(&c.id))
|
||||||
|
.map(|c| db::models::NewHoliday {
|
||||||
|
untis_id: c.id,
|
||||||
|
schoolyear_id,
|
||||||
|
name: &c.name,
|
||||||
|
long_name: &c.long_name,
|
||||||
|
start_date: c.start_date,
|
||||||
|
end_date: c.end_date,
|
||||||
|
})
|
||||||
|
.collect::<Vec<db::models::NewHoliday>>(),
|
||||||
|
)
|
||||||
|
.execute(db_conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[celery::task]
|
#[celery::task]
|
||||||
pub async fn update_meta() -> TaskResult<()> {
|
pub async fn update_meta() -> TaskResult<()> {
|
||||||
let dur = Duration::from_secs(2);
|
let dur = Duration::from_secs(2);
|
||||||
|
@ -50,6 +325,11 @@ pub async fn update_meta() -> TaskResult<()> {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
||||||
};
|
};
|
||||||
|
if let Err(e) = client.login().await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
thread::sleep(dur);
|
||||||
|
|
||||||
let db_conn = &mut match db::POOL.get() {
|
let db_conn = &mut match db::POOL.get() {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
||||||
|
@ -60,8 +340,38 @@ pub async fn update_meta() -> TaskResult<()> {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
Err(e) => return Err(TaskError::UnexpectedError(format!("{:?}", e))),
|
||||||
};
|
};
|
||||||
dbg!(&schoolyear_id);
|
|
||||||
thread::sleep(dur);
|
thread::sleep(dur);
|
||||||
|
if let Err(e) = fetch_current_tenant(&client, db_conn, schoolyear_id).await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
thread::sleep(dur);
|
||||||
|
if let Err(e) = fetch_timegrid(&client, db_conn, schoolyear_id).await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
thread::sleep(dur);
|
||||||
|
if let Err(e) = fetch_teachers(&client, db_conn, schoolyear_id).await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
thread::sleep(dur);
|
||||||
|
if let Err(e) = fetch_classes(&client, db_conn, schoolyear_id).await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
thread::sleep(dur);
|
||||||
|
if let Err(e) = fetch_subjects(&client, db_conn, schoolyear_id).await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
thread::sleep(dur);
|
||||||
|
if let Err(e) = fetch_rooms(&client, db_conn, schoolyear_id).await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
thread::sleep(dur);
|
||||||
|
if let Err(e) = fetch_departments(&client, db_conn, schoolyear_id).await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
thread::sleep(dur);
|
||||||
|
if let Err(e) = fetch_holidays(&client, db_conn, schoolyear_id).await {
|
||||||
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(e) = client.logout().await {
|
if let Err(e) = client.logout().await {
|
||||||
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
return Err(TaskError::UnexpectedError(format!("{:?}", e)));
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<meta name="generator" content="BVplan" />
|
<meta name="generator" content="BVplan" />
|
||||||
|
|
||||||
<script id="data" type="application/json">{{ data.substitutions.len()|json|safe }}</script>
|
<script id="data-element-count" type="application/json">{{ data.substitutions.len()|json|safe }}</script>
|
||||||
|
|
||||||
<script
|
<script
|
||||||
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"
|
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js"
|
||||||
|
@ -227,8 +227,8 @@
|
||||||
Wow
|
Wow
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="https://git.dergrimm.net/bvplan">
|
<a href="https://git.dergrimm.net/dergrimm/bvplan">
|
||||||
https://git.dergrimm.net/bvplan
|
https://git.dergrimm.net/dergrimm/bvplan
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -252,10 +252,14 @@
|
||||||
}, 30_000);
|
}, 30_000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const elementCount = JSON.parse($("#data").text());
|
const elementCount = JSON.parse($("#data-element-count").text());
|
||||||
const waitDelay = 10_000;
|
const waitDelay = 10_000;
|
||||||
const scrollDuration = elementCount * 200;
|
const scrollDuration = elementCount * 200;
|
||||||
|
|
||||||
|
function reload() {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
function scrollUp() {
|
function scrollUp() {
|
||||||
$("html, body").animate(
|
$("html, body").animate(
|
||||||
{
|
{
|
||||||
|
@ -264,9 +268,7 @@
|
||||||
scrollDuration,
|
scrollDuration,
|
||||||
"linear"
|
"linear"
|
||||||
);
|
);
|
||||||
setTimeout(function () {
|
setTimeout(reload, scrollDuration);
|
||||||
window.location.reload();
|
|
||||||
}, scrollDuration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollDown() {
|
function scrollDown() {
|
||||||
|
@ -281,7 +283,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
setTimeout(scrollDown, waitDelay);
|
setTimeout($(window).height() > $(window).height() ? scrollDown : reload, waitDelay);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -83,6 +83,8 @@ services:
|
||||||
<<: *bvplan
|
<<: *bvplan
|
||||||
command: worker
|
command: worker
|
||||||
volumes:
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- ./data/backups:/backups
|
- ./data/backups:/backups
|
||||||
|
|
||||||
web:
|
web:
|
||||||
|
@ -93,6 +95,9 @@ services:
|
||||||
- rabbitmq
|
- rabbitmq
|
||||||
- worker
|
- worker
|
||||||
- redis
|
- redis
|
||||||
|
volumes:
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db:
|
db:
|
||||||
|
|
Loading…
Reference in a new issue