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 { // 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, 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, 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 { // 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 { 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 }