135 lines
3.7 KiB
Rust
135 lines
3.7 KiB
Rust
use chrono::NaiveDateTime;
|
|
use sqlx::PgPool;
|
|
|
|
use crate::database::{entities::Schedule, types::DayOfWeek};
|
|
|
|
pub async fn add_schedule(
|
|
pool: &PgPool,
|
|
user_id: i32,
|
|
enter_time: NaiveDateTime,
|
|
day_of_week: DayOfWeek,
|
|
out_time: NaiveDateTime,
|
|
) -> Result<Schedule, sqlx::Error> {
|
|
// Keep compatible with legacy DBs that have an extra `shift` column.
|
|
// Try insert with `shift` first, fall back to 4-column insert if the column was dropped/never created.
|
|
let with_shift = sqlx::query_as::<_, Schedule>(
|
|
r#"
|
|
INSERT INTO schedules (user_id, enter_time, day_of_week, shift, out_time)
|
|
VALUES ($1, $2, $3, 'morning', $4)
|
|
RETURNING id, user_id, enter_time, day_of_week, out_time, date_created, date_updated
|
|
"#,
|
|
)
|
|
.bind(user_id)
|
|
.bind(enter_time)
|
|
.bind(day_of_week)
|
|
.bind(out_time)
|
|
.fetch_one(pool)
|
|
.await;
|
|
|
|
match with_shift {
|
|
Ok(schedule) => Ok(schedule),
|
|
Err(_) => {
|
|
sqlx::query_as::<_, Schedule>(
|
|
r#"
|
|
INSERT INTO schedules (user_id, enter_time, day_of_week, out_time)
|
|
VALUES ($1, $2, $3, $4)
|
|
RETURNING id, user_id, enter_time, day_of_week, out_time, date_created, date_updated
|
|
"#,
|
|
)
|
|
.bind(user_id)
|
|
.bind(enter_time)
|
|
.bind(day_of_week)
|
|
.bind(out_time)
|
|
.fetch_one(pool)
|
|
.await
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn list_schedules(pool: &PgPool) -> Result<Vec<Schedule>, sqlx::Error> {
|
|
sqlx::query_as::<_, Schedule>(
|
|
r#"
|
|
SELECT id, user_id, enter_time, day_of_week, out_time, date_created, date_updated
|
|
FROM schedules
|
|
ORDER BY day_of_week, user_id
|
|
"#,
|
|
)
|
|
.fetch_all(pool)
|
|
.await
|
|
}
|
|
|
|
pub async fn list_schedules_for_company(
|
|
pool: &PgPool,
|
|
company_id: i32,
|
|
) -> Result<Vec<Schedule>, sqlx::Error> {
|
|
sqlx::query_as::<_, Schedule>(
|
|
r#"
|
|
SELECT schedules.id, schedules.user_id, schedules.enter_time, schedules.day_of_week,
|
|
schedules.out_time, schedules.date_created, schedules.date_updated
|
|
FROM schedules
|
|
INNER JOIN company_users ON company_users.user_id = schedules.user_id
|
|
WHERE company_users.company_id = $1
|
|
ORDER BY schedules.day_of_week, schedules.user_id
|
|
"#,
|
|
)
|
|
.bind(company_id)
|
|
.fetch_all(pool)
|
|
.await
|
|
}
|
|
|
|
pub async fn delete_schedules_for_company(
|
|
pool: &PgPool,
|
|
company_id: i32,
|
|
) -> Result<(), sqlx::Error> {
|
|
sqlx::query(
|
|
r#"
|
|
DELETE FROM schedules
|
|
USING company_users
|
|
WHERE company_users.user_id = schedules.user_id
|
|
AND company_users.company_id = $1
|
|
"#,
|
|
)
|
|
.bind(company_id)
|
|
.execute(pool)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn clock_in(
|
|
pool: &PgPool,
|
|
user_id: i32,
|
|
now: NaiveDateTime,
|
|
day_of_week: DayOfWeek,
|
|
) -> Result<Schedule, sqlx::Error> {
|
|
// out_time is required in reference API, initialize with enter_time and let clock-out update it
|
|
add_schedule(pool, user_id, now, day_of_week, now).await
|
|
}
|
|
|
|
pub async fn clock_out(
|
|
pool: &PgPool,
|
|
user_id: i32,
|
|
day_of_week: DayOfWeek,
|
|
out_time: NaiveDateTime,
|
|
) -> Result<Schedule, sqlx::Error> {
|
|
sqlx::query_as::<_, Schedule>(
|
|
r#"
|
|
UPDATE schedules
|
|
SET out_time = $3, date_updated = NOW()
|
|
WHERE id = (
|
|
SELECT id
|
|
FROM schedules
|
|
WHERE user_id = $1 AND day_of_week = $2
|
|
ORDER BY enter_time DESC
|
|
LIMIT 1
|
|
)
|
|
RETURNING id, user_id, enter_time, day_of_week, out_time, date_created, date_updated
|
|
"#,
|
|
)
|
|
.bind(user_id)
|
|
.bind(day_of_week)
|
|
.bind(out_time)
|
|
.fetch_one(pool)
|
|
.await
|
|
}
|