headless_lms_server/controllers/main_frontend/
teacher_grading_decisions.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use crate::prelude::*;
use headless_lms_models::{
    exercises::get_exercise_by_id,
    library::user_exercise_state_updater,
    teacher_grading_decisions::{NewTeacherGradingDecision, TeacherDecisionType},
    user_exercise_states::UserExerciseState,
};

/**
POST `/api/v0/main-frontend/teacher-grading-decisions` - Creates a new teacher grading decision, overriding the points a user has received from an exercise.
*/
#[instrument(skip(pool))]
async fn create_teacher_grading_decision(
    payload: web::Json<NewTeacherGradingDecision>,
    pool: web::Data<PgPool>,
    user: AuthUser,
) -> ControllerResult<web::Json<UserExerciseState>> {
    let action = &payload.action;
    let exercise_id = payload.exercise_id;
    let user_exercise_state_id = payload.user_exercise_state_id;
    let manual_points = payload.manual_points;
    let justification = &payload.justification;
    let hidden = payload.hidden;
    let mut conn = pool.acquire().await?;
    let token = authorize(
        &mut conn,
        Act::Edit,
        Some(user.id),
        Res::Exercise(exercise_id),
    )
    .await?;
    let points_given;
    if *action == TeacherDecisionType::FullPoints {
        let exercise = get_exercise_by_id(&mut conn, exercise_id).await?;
        points_given = exercise.score_maximum as f32;
    } else if *action == TeacherDecisionType::ZeroPoints {
        points_given = 0.0;
    } else if *action == TeacherDecisionType::CustomPoints {
        points_given = manual_points.unwrap_or(0.0);
    } else if *action == TeacherDecisionType::SuspectedPlagiarism {
        points_given = 0.0;
    } else {
        return Err(ControllerError::new(
            ControllerErrorType::BadRequest,
            "Invalid query".to_string(),
            None,
        ));
    }

    info!(
        "Teacher took the following action: {:?}. Points given: {:?}.",
        &action, points_given
    );

    let mut tx = conn.begin().await?;

    let _res = models::teacher_grading_decisions::add_teacher_grading_decision(
        &mut tx,
        user_exercise_state_id,
        *action,
        points_given,
        Some(user.id),
        justification.clone(),
        hidden,
    )
    .await?;

    let new_user_exercise_state =
        user_exercise_state_updater::update_user_exercise_state(&mut tx, user_exercise_state_id)
            .await?;

    if let Some(course_instance_id) = new_user_exercise_state.course_instance_id {
        // Since the teacher just reviewed the submission we should mark possible peer review queue entries so that they won't be given to others to review. Receiving peer reviews for this answer now would not make much sense.
        models::peer_review_queue_entries::remove_queue_entries_for_unusual_reason(
            &mut tx,
            new_user_exercise_state.user_id,
            new_user_exercise_state.exercise_id,
            course_instance_id,
        )
        .await?;
    }

    tx.commit().await?;

    token.authorized_ok(web::Json(new_user_exercise_state))
}

pub fn _add_routes(cfg: &mut ServiceConfig) {
    cfg.route("", web::post().to(create_teacher_grading_decision));
}