Skip to main content

headless_lms_server/controllers/main_frontend/course_credit_registrations/
enrolment_recheck.rs

1//! A teacher asking the pipeline to look for a student's enrolment again.
2
3use headless_lms_models::credit_registration_admin_actions::{
4    COURSE_TEACHER_ROLE, CreditRegistrationAdminAction, CreditRegistrationAdminActionTarget,
5    NewCreditRegistrationAdminAction,
6};
7use headless_lms_models::credit_registration_events::CreditRegistrationEventKind;
8use headless_lms_models::credit_registrations::CreditRegistrationState;
9
10use headless_lms_models::library::credit_registration::enrolment_check_schedule::EnrolmentCheckSource;
11use headless_lms_models::library::credit_registration::enrolment_checks::CheckRequestOutcome;
12
13use crate::controllers::main_frontend::credit_registrations::RequestCreditRegistrationEnrolmentRecheckResult;
14use crate::domain::credit_registration::enrolment_recheck::{
15    RecheckTarget, start_enrolment_recheck,
16};
17use crate::domain::error::missing_controller_error;
18use crate::prelude::*;
19
20/**
21POST
22`/api/v0/main-frontend/course-credit-registrations/registrations/{credit_registration_id}/recheck-enrolment`
23- Asks the pipeline to look for an enrolment again, for a row parked because the study registry had
24none.
25
26Shares the student's limit on asking, so between them they cannot start more than one check in 30
27minutes. Authorized on the row's own course, like the retry.
28*/
29#[instrument(skip(pool))]
30#[utoipa::path(
31    post,
32    path = "/registrations/{credit_registration_id}/recheck-enrolment",
33    operation_id = "recheckCreditRegistrationEnrolment",
34    tag = "course-credit-registrations",
35    params(("credit_registration_id" = Uuid, Path, description = "Credit registration id")),
36    responses(
37        (status = 200, description = "Whether a recheck was started", body = RequestCreditRegistrationEnrolmentRecheckResult),
38        (status = 400, description = "The registration is not waiting for an enrolment"),
39        (status = 404, description = "No such registration")
40    )
41)]
42pub async fn recheck_credit_registration_enrolment(
43    user: AuthUser,
44    pool: web::Data<PgPool>,
45    credit_registration_id: web::Path<Uuid>,
46) -> ControllerResult<web::Json<RequestCreditRegistrationEnrolmentRecheckResult>> {
47    let mut conn = pool.acquire().await?;
48    let id = *credit_registration_id;
49    let row = models::credit_registrations::get_teacher_facing_by_id(&mut conn, id)
50        .await?
51        .ok_or_else(missing_controller_error(
52            ControllerErrorType::NotFound,
53            "Not found.".to_string(),
54        ))?;
55    let token =
56        super::authorize_credit_registration_teacher(&mut conn, user.id, row.course_id).await?;
57
58    if row.state != CreditRegistrationState::NoUsableEnrolment {
59        return Err(controller_err!(
60            BadRequest,
61            "This registration is not waiting for an enrolment.".to_string()
62        ));
63    }
64    let mut tx = conn.begin().await?;
65    let outcome = start_enrolment_recheck(
66        &mut tx,
67        user.id,
68        RecheckTarget {
69            registration_id: id,
70            course_module_completion_id: row.course_module_completion_id,
71        },
72        EnrolmentCheckSource::TeacherRequest,
73        CreditRegistrationEventKind::AdminAction,
74        "A teacher of the course asked us to check for an enrolment again.",
75    )
76    .await?;
77    if matches!(
78        outcome,
79        CheckRequestOutcome::TooSoon | CheckRequestOutcome::NotWaiting
80    ) {
81        tx.commit().await?;
82        return token.authorized_ok(web::Json(RequestCreditRegistrationEnrolmentRecheckResult {
83            recheck_started: false,
84        }));
85    }
86    models::credit_registration_admin_actions::record(
87        &mut tx,
88        &NewCreditRegistrationAdminAction {
89            target_id: Some(id),
90            actor_course_id: Some(row.course_id),
91            before_state: Some(row.state),
92            affected_row_count: Some(1),
93            ..NewCreditRegistrationAdminAction::new(
94                CreditRegistrationAdminAction::ForceRecheck,
95                CreditRegistrationAdminActionTarget::CreditRegistration,
96                user.id,
97                COURSE_TEACHER_ROLE,
98            )
99        },
100    )
101    .await?;
102    tx.commit().await?;
103
104    token.authorized_ok(web::Json(RequestCreditRegistrationEnrolmentRecheckResult {
105        recheck_started: outcome.started_check(),
106    }))
107}
108
109pub fn _add_routes(cfg: &mut ServiceConfig) {
110    cfg.route(
111        "/registrations/{credit_registration_id}/recheck-enrolment",
112        web::post().to(recheck_credit_registration_enrolment),
113    );
114}