diff --git a/services/headless-lms/models/.sqlx/query-babe94146c1a983a5ec39d5b9007fca3eab050b172236259ccd8711a5fa0ceb2.json b/services/headless-lms/models/.sqlx/query-babe94146c1a983a5ec39d5b9007fca3eab050b172236259ccd8711a5fa0ceb2.json new file mode 100644 index 00000000000..eea8fe9f3ca --- /dev/null +++ b/services/headless-lms/models/.sqlx/query-babe94146c1a983a5ec39d5b9007fca3eab050b172236259ccd8711a5fa0ceb2.json @@ -0,0 +1,68 @@ +{ + "db_name": "PostgreSQL", + "query": "\nSELECT prqe.*\nFROM peer_review_queue_entries prqe\n JOIN user_exercise_states ues ON (\n prqe.user_id = ues.user_id\n AND prqe.exercise_id = ues.exercise_id\n AND prqe.course_instance_id = ues.course_instance_id\n )\nWHERE prqe.course_instance_id = $1\n AND ues.reviewing_stage = 'waiting_for_manual_grading'\n AND prqe.created_at < $2\n AND prqe.deleted_at IS NULL\n AND ues.deleted_at IS NULL\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 2, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 3, + "name": "deleted_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "user_id", + "type_info": "Uuid" + }, + { + "ordinal": 5, + "name": "exercise_id", + "type_info": "Uuid" + }, + { + "ordinal": 6, + "name": "course_instance_id", + "type_info": "Uuid" + }, + { + "ordinal": 7, + "name": "receiving_peer_reviews_exercise_slide_submission_id", + "type_info": "Uuid" + }, + { + "ordinal": 8, + "name": "received_enough_peer_reviews", + "type_info": "Bool" + }, + { + "ordinal": 9, + "name": "peer_review_priority", + "type_info": "Int4" + }, + { + "ordinal": 10, + "name": "removed_from_queue_for_unusual_reason", + "type_info": "Bool" + } + ], + "parameters": { + "Left": ["Uuid", "Timestamptz"] + }, + "nullable": [false, false, false, true, false, false, false, false, false, false, false] + }, + "hash": "babe94146c1a983a5ec39d5b9007fca3eab050b172236259ccd8711a5fa0ceb2" +} diff --git a/services/headless-lms/models/src/peer_review_queue_entries.rs b/services/headless-lms/models/src/peer_review_queue_entries.rs index 36975b04bde..cad74175e3b 100644 --- a/services/headless-lms/models/src/peer_review_queue_entries.rs +++ b/services/headless-lms/models/src/peer_review_queue_entries.rs @@ -393,6 +393,36 @@ WHERE course_instance_id = $1 Ok(res) } +/// Returns entries that have been waiting for teacher to review them for more than `timestamp`. The teacher is supposed to review an answer when the `user_exercise_states` `reviewing_stage` is `WaitingForManualGrading`. +pub async fn get_entries_that_need_teacher_review_and_are_older_than_with_course_instance_id( + conn: &mut PgConnection, + course_instance_id: Uuid, + timestamp: DateTime, +) -> ModelResult> { + let res = sqlx::query_as!( + PeerReviewQueueEntry, + " +SELECT prqe.* +FROM peer_review_queue_entries prqe + JOIN user_exercise_states ues ON ( + prqe.user_id = ues.user_id + AND prqe.exercise_id = ues.exercise_id + AND prqe.course_instance_id = ues.course_instance_id + ) +WHERE prqe.course_instance_id = $1 + AND ues.reviewing_stage = 'waiting_for_manual_grading' + AND prqe.created_at < $2 + AND prqe.deleted_at IS NULL + AND ues.deleted_at IS NULL + ", + course_instance_id, + timestamp + ) + .fetch_all(conn) + .await?; + Ok(res) +} + pub async fn get_entries_that_need_reviews_and_are_older_than_with_exercise_id( conn: &mut PgConnection, exercise_id: Uuid, diff --git a/services/headless-lms/server/src/programs/peer_review_updater.rs b/services/headless-lms/server/src/programs/peer_review_updater.rs index 91b7fb43d29..ebffb1c7ceb 100644 --- a/services/headless-lms/server/src/programs/peer_review_updater.rs +++ b/services/headless-lms/server/src/programs/peer_review_updater.rs @@ -67,9 +67,9 @@ async fn process_course_instance( let pass_automatically_cutoff = earliest_manual_review_cutoff - chrono::Duration::days(90); // Process automatic pass cases - let should_pass = headless_lms_models::peer_review_queue_entries::get_entries_that_need_reviews_and_are_older_than(conn, course_instance.id, pass_automatically_cutoff).await?; + let should_pass = headless_lms_models::peer_review_queue_entries::get_entries_that_need_teacher_review_and_are_older_than_with_course_instance_id(conn, course_instance.id, pass_automatically_cutoff).await?; if !should_pass.is_empty() { - info!(course_instance_id = ?course_instance.id, "Found {:?} answers that have been added to the peer review queue before {:?} and have not received enough peer reviews or have not been reviewed manually. Giving them full points.", should_pass.len(), pass_automatically_cutoff); + info!(course_instance_id = ?course_instance.id, "Found {:?} answers that have been added to the peer review queue before {:?}. The teacher has not reviewed the answers manually after 3 months. Giving them full points.", should_pass.len(), pass_automatically_cutoff); for peer_review_queue_entry in should_pass { let _res = peer_review_queue_entries::remove_from_queue_and_give_full_points( conn,