headless_lms_server/controllers/main_frontend/credit_registration_admin/
materialize.rs1use headless_lms_models::credit_registration_admin_actions::{
4 CreditRegistrationAdminAction, CreditRegistrationAdminActionTarget, GLOBAL_ADMIN_ROLE,
5 NewCreditRegistrationAdminAction,
6};
7use headless_lms_models::credit_registrations;
8use headless_lms_models::library::credit_registration::materialize::{
9 MATERIALIZE_LIMIT, ensure_registration_rows_for_eligible_completions,
10};
11use headless_lms_models::library::credit_registration::preconditions::{
12 PRECONDITIONS_LIMIT, recompute_preconditions,
13};
14use utoipa::ToSchema;
15
16use crate::domain::credit_registration_phases::CreditRegistrationPhase;
17use crate::prelude::*;
18
19use super::authorize_credit_registration_admin;
20
21#[derive(Debug, Deserialize, ToSchema)]
22pub struct AdminMaterializePayload {
23 pub reason: Option<String>,
24}
25
26#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
27pub struct AdminMaterializeResult {
28 pub created_registration_count: i64,
29 pub moved_registration_count: i64,
30}
31
32#[instrument(skip(pool, payload))]
41#[utoipa::path(
42 post,
43 path = "/materialize",
44 operation_id = "adminMaterializeCreditRegistrations",
45 tag = "credit-registration-admin",
46 request_body = AdminMaterializePayload,
47 responses(
48 (status = 200, description = "How many rows were created and moved", body = AdminMaterializeResult)
49 )
50)]
51pub async fn admin_materialize_credit_registrations(
52 user: AuthUser,
53 pool: web::Data<PgPool>,
54 payload: web::Json<AdminMaterializePayload>,
55) -> ControllerResult<web::Json<AdminMaterializeResult>> {
56 let mut conn = pool.acquire().await?;
57 let token = authorize_credit_registration_admin(&mut conn, user.id).await?;
58
59 let mut tx = conn.begin().await?;
60 let scope = credit_registrations::RegistrationScope::default();
61 let created_registration_count =
62 ensure_registration_rows_for_eligible_completions(&mut tx, &scope, MATERIALIZE_LIMIT)
63 .await?;
64 let moved_registration_count =
65 recompute_preconditions(&mut tx, &scope, PRECONDITIONS_LIMIT).await?;
66 models::credit_registration_admin_actions::record(
67 &mut tx,
68 &NewCreditRegistrationAdminAction {
69 target_phase: Some(CreditRegistrationPhase::Materialize.as_str().to_string()),
70 reason: payload.reason.clone(),
71 details: Some(serde_json::json!({
72 "created_registration_count": created_registration_count,
73 "moved_registration_count": moved_registration_count,
74 })),
75 affected_row_count: Some(
76 i32::try_from(created_registration_count + moved_registration_count)
77 .unwrap_or(i32::MAX),
78 ),
79 ..NewCreditRegistrationAdminAction::new(
80 CreditRegistrationAdminAction::RequeueBatch,
81 CreditRegistrationAdminActionTarget::Phase,
82 user.id,
83 GLOBAL_ADMIN_ROLE,
84 )
85 },
86 )
87 .await?;
88 tx.commit().await?;
89
90 token.authorized_ok(web::Json(AdminMaterializeResult {
91 created_registration_count,
92 moved_registration_count,
93 }))
94}
95
96pub fn _add_routes(cfg: &mut ServiceConfig) {
97 cfg.route(
98 "/materialize",
99 web::post().to(admin_materialize_credit_registrations),
100 );
101}