343 lines
12 KiB
Rust
343 lines
12 KiB
Rust
use chrono::{NaiveDate, NaiveTime};
|
|
use sqlx::{query, PgPool};
|
|
|
|
use super::{Area, AvailabilityChangeset, Function, Result, Role, User};
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Availability {
|
|
pub id: i32,
|
|
pub user_id: i32,
|
|
pub user: Option<User>,
|
|
pub date: NaiveDate,
|
|
pub time: AvailabilityTime,
|
|
pub comment: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub enum AvailabilityTime {
|
|
WholeDay,
|
|
Temporarily(NaiveTime, NaiveTime),
|
|
}
|
|
|
|
impl Availability {
|
|
// TODO: fix db name
|
|
pub async fn create(
|
|
pool: &PgPool,
|
|
user_id: i32,
|
|
date: NaiveDate,
|
|
changeset: AvailabilityChangeset,
|
|
) -> Result<()> {
|
|
let (start, end) = if let AvailabilityTime::Temporarily(s, e) = changeset.time {
|
|
(Some(s), Some(e))
|
|
} else {
|
|
(None, None)
|
|
};
|
|
|
|
query!(
|
|
r#"
|
|
INSERT INTO availabillity (userId, date, startTime, endTime, comment)
|
|
VALUES ($1, $2, $3, $4, $5);
|
|
"#,
|
|
user_id,
|
|
date,
|
|
start,
|
|
end,
|
|
changeset.comment
|
|
)
|
|
.execute(pool)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn read_by_date_and_area_including_user(
|
|
pool: &PgPool,
|
|
date: NaiveDate,
|
|
area_id: i32,
|
|
) -> Result<Vec<Availability>> {
|
|
let records = query!(
|
|
r##"
|
|
SELECT
|
|
availabillity.id,
|
|
availabillity.userId,
|
|
availabillity.date,
|
|
availabillity.startTime,
|
|
availabillity.endTime,
|
|
availabillity.comment,
|
|
user_.name,
|
|
user_.email,
|
|
user_.password,
|
|
user_.salt,
|
|
user_.role AS "role: Role",
|
|
user_.function AS "function: Function",
|
|
user_.areaId,
|
|
user_.locked,
|
|
user_.lastLogin,
|
|
user_.receiveNotifications
|
|
FROM availabillity
|
|
JOIN user_ ON availabillity.userId = user_.id
|
|
WHERE availabillity.date = $1
|
|
AND user_.areaId = $2;
|
|
"##,
|
|
date,
|
|
area_id
|
|
)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
let availabillities = records
|
|
.iter()
|
|
.map(|r| Availability {
|
|
id: r.id,
|
|
user_id: r.userid,
|
|
user: Some(User {
|
|
id: r.userid,
|
|
name: r.name.clone(),
|
|
email: r.email.clone(),
|
|
password: r.password.clone(),
|
|
salt: r.salt.clone(),
|
|
role: r.role.clone(),
|
|
function: r.function.clone(),
|
|
area_id: r.areaid,
|
|
area: None,
|
|
locked: r.locked,
|
|
last_login: r.lastlogin,
|
|
receive_notifications: r.receivenotifications,
|
|
}),
|
|
date: r.date,
|
|
time: match (r.starttime, r.endtime) {
|
|
(Some(start), Some(end)) => AvailabilityTime::Temporarily(start, end),
|
|
(_, _) => AvailabilityTime::WholeDay,
|
|
},
|
|
comment: r.comment.clone(),
|
|
})
|
|
.collect();
|
|
|
|
Ok(availabillities)
|
|
}
|
|
|
|
pub async fn read_by_id_including_user(pool: &PgPool, id: i32) -> Result<Option<Availability>> {
|
|
let record = query!(
|
|
r##"
|
|
SELECT
|
|
availabillity.id,
|
|
availabillity.userId,
|
|
availabillity.date,
|
|
availabillity.startTime,
|
|
availabillity.endTime,
|
|
availabillity.comment,
|
|
user_.name,
|
|
user_.email,
|
|
user_.password,
|
|
user_.salt,
|
|
user_.role AS "role: Role",
|
|
user_.function AS "function: Function",
|
|
user_.areaId,
|
|
user_.locked,
|
|
user_.lastLogin,
|
|
user_.receiveNotifications
|
|
FROM availabillity
|
|
LEFT JOIN assignment ON availabillity.Id = assignment.availabillityId
|
|
JOIN user_ ON availabillity.userId = user_.id
|
|
WHERE availabillity.id = $1;
|
|
"##,
|
|
id
|
|
)
|
|
.fetch_optional(pool)
|
|
.await?;
|
|
|
|
let availabillity = record.and_then(|r| {
|
|
Some(Availability {
|
|
id: r.id,
|
|
user_id: r.userid,
|
|
user: Some(User {
|
|
id: r.userid,
|
|
name: r.name.clone(),
|
|
email: r.email.clone(),
|
|
password: r.password.clone(),
|
|
salt: r.salt.clone(),
|
|
role: r.role.clone(),
|
|
function: r.function.clone(),
|
|
area_id: r.areaid,
|
|
area: None,
|
|
locked: r.locked,
|
|
last_login: r.lastlogin,
|
|
receive_notifications: r.receivenotifications,
|
|
}),
|
|
date: r.date,
|
|
time: match (r.starttime, r.endtime) {
|
|
(Some(start), Some(end)) => AvailabilityTime::Temporarily(start, end),
|
|
(_, _) => AvailabilityTime::WholeDay,
|
|
},
|
|
comment: r.comment.clone(),
|
|
})
|
|
});
|
|
|
|
Ok(availabillity)
|
|
}
|
|
|
|
pub async fn read_by_id(pool: &PgPool, id: i32) -> Result<Option<Availability>> {
|
|
let record = query!("SELECT * FROM availabillity WHERE id = $1", id)
|
|
.fetch_optional(pool)
|
|
.await?;
|
|
|
|
let availabillity = record.and_then(|record| {
|
|
Some(Availability {
|
|
id: record.id,
|
|
user_id: record.userid,
|
|
user: None,
|
|
date: record.date,
|
|
time: match (record.starttime, record.endtime) {
|
|
(Some(start), Some(end)) => AvailabilityTime::Temporarily(start, end),
|
|
(_, _) => AvailabilityTime::WholeDay,
|
|
},
|
|
comment: record.comment.clone(),
|
|
})
|
|
});
|
|
|
|
Ok(availabillity)
|
|
}
|
|
|
|
pub async fn read_for_export(
|
|
pool: &PgPool,
|
|
date_range: (NaiveDate, NaiveDate),
|
|
area_id: i32,
|
|
) -> Result<Vec<Availability>> {
|
|
let records = query!(
|
|
r##"
|
|
SELECT
|
|
availabillity.id,
|
|
availabillity.userId,
|
|
availabillity.date,
|
|
availabillity.startTime,
|
|
availabillity.endTime,
|
|
availabillity.comment,
|
|
user_.name,
|
|
user_.email,
|
|
user_.password,
|
|
user_.salt,
|
|
user_.role AS "role: Role",
|
|
user_.function AS "function: Function",
|
|
user_.areaId,
|
|
user_.locked,
|
|
user_.lastLogin,
|
|
user_.receiveNotifications,
|
|
area.name AS areaName
|
|
FROM availabillity
|
|
JOIN user_ ON availabillity.userId = user_.id
|
|
JOIN area ON user_.areaId = area.id
|
|
WHERE user_.areaId = $1 AND
|
|
availabillity.date >= $2 AND
|
|
availabillity.date <= $3;
|
|
"##,
|
|
area_id,
|
|
date_range.0,
|
|
date_range.1
|
|
)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
let availabillities = records
|
|
.iter()
|
|
.map(|r| Availability {
|
|
id: r.id,
|
|
user_id: r.userid,
|
|
user: Some(User {
|
|
id: r.userid,
|
|
name: r.name.clone(),
|
|
email: r.email.clone(),
|
|
password: r.password.clone(),
|
|
salt: r.salt.clone(),
|
|
role: r.role.clone(),
|
|
function: r.function.clone(),
|
|
area_id: r.areaid,
|
|
area: Some(Area {
|
|
id: r.areaid,
|
|
name: r.areaname.clone(),
|
|
}),
|
|
locked: r.locked,
|
|
last_login: r.lastlogin,
|
|
receive_notifications: r.receivenotifications,
|
|
}),
|
|
date: r.date,
|
|
time: match (r.starttime, r.endtime) {
|
|
(Some(start), Some(end)) => AvailabilityTime::Temporarily(start, end),
|
|
(_, _) => AvailabilityTime::WholeDay,
|
|
},
|
|
comment: r.comment.clone(),
|
|
})
|
|
.collect();
|
|
|
|
Ok(availabillities)
|
|
}
|
|
|
|
pub async fn read_by_user_and_date(
|
|
pool: &PgPool,
|
|
user_id: i32,
|
|
date: &NaiveDate,
|
|
) -> Result<Vec<Availability>> {
|
|
let records = query!(
|
|
r##"
|
|
SELECT
|
|
availabillity.id,
|
|
availabillity.userId,
|
|
availabillity.date,
|
|
availabillity.startTime,
|
|
availabillity.endTime,
|
|
availabillity.comment
|
|
FROM availabillity
|
|
WHERE availabillity.userId = $1
|
|
AND availabillity.date = $2;
|
|
"##,
|
|
user_id,
|
|
date
|
|
)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
let availabillities = records
|
|
.iter()
|
|
.map(|r| Availability {
|
|
id: r.id,
|
|
user_id: r.userid,
|
|
user: None,
|
|
date: r.date,
|
|
time: match (r.starttime, r.endtime) {
|
|
(Some(start), Some(end)) => AvailabilityTime::Temporarily(start, end),
|
|
(_, _) => AvailabilityTime::WholeDay,
|
|
},
|
|
comment: r.comment.clone(),
|
|
})
|
|
.collect();
|
|
|
|
Ok(availabillities)
|
|
}
|
|
|
|
pub async fn update(pool: &PgPool, id: i32, changeset: AvailabilityChangeset) -> Result<()> {
|
|
let (start, end) = if let AvailabilityTime::Temporarily(s, e) = changeset.time {
|
|
(Some(s), Some(e))
|
|
} else {
|
|
(None, None)
|
|
};
|
|
|
|
query!(
|
|
"UPDATE availabillity SET startTime = $1, endTime = $2, comment = $3 WHERE id = $4",
|
|
start,
|
|
end,
|
|
changeset.comment,
|
|
id
|
|
)
|
|
.execute(pool)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn delete(pool: &PgPool, id: i32) -> Result<()> {
|
|
query!("DELETE FROM availabillity WHERE id = $1", id)
|
|
.execute(pool)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|