headless_lms_server/controllers/main_frontend/course_credit_registrations/
actions.rs1use headless_lms_models::credit_registration_admin_actions::{
5 CreditRegistrationAdminAction, CreditRegistrationAdminActionFilters,
6 CreditRegistrationAdminActionTarget,
7};
8use headless_lms_models::credit_registrations::CreditRegistrationState;
9use std::collections::HashMap;
10use utoipa::ToSchema;
11
12use crate::prelude::*;
13
14const MAX_ACTIONS: i64 = 100;
17
18#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
21pub struct CourseCreditRegistrationAction {
22 pub id: Uuid,
23 pub created_at: DateTime<Utc>,
24 pub action: CreditRegistrationAdminAction,
25 pub target_kind: CreditRegistrationAdminActionTarget,
26 pub target_id: Option<Uuid>,
27 pub actor_user_id: Uuid,
28 pub actor_role: String,
31 pub actor_first_name: Option<String>,
32 pub actor_last_name: Option<String>,
33 pub reason: Option<String>,
34 pub before_state: Option<CreditRegistrationState>,
35 pub after_state: Option<CreditRegistrationState>,
36 pub affected_row_count: Option<i32>,
37}
38
39#[instrument(skip(pool))]
44#[utoipa::path(
45 get,
46 path = "/courses/{course_id}/actions",
47 operation_id = "getCourseCreditRegistrationActions",
48 tag = "course-credit-registrations",
49 params(("course_id" = Uuid, Path, description = "Course id")),
50 responses(
51 (status = 200, description = "The course's manual actions", body = Vec<CourseCreditRegistrationAction>)
52 )
53)]
54pub async fn get_course_credit_registration_actions(
55 user: AuthUser,
56 pool: web::Data<PgPool>,
57 course_id: web::Path<Uuid>,
58) -> ControllerResult<web::Json<Vec<CourseCreditRegistrationAction>>> {
59 let mut conn = pool.acquire().await?;
60 let token =
61 super::authorize_credit_registration_teacher(&mut conn, user.id, *course_id).await?;
62
63 let records = models::credit_registration_admin_actions::get_page(
64 &mut conn,
65 &CreditRegistrationAdminActionFilters {
66 course_id: Some(*course_id),
67 ..Default::default()
68 },
69 MAX_ACTIONS,
70 0,
71 )
72 .await?
73 .into_iter()
74 .map(|row| row.action)
75 .collect::<Vec<_>>();
76 let actor_ids: Vec<Uuid> = records.iter().map(|record| record.actor_user_id).collect();
77 let actors: HashMap<Uuid, (Option<String>, Option<String>)> =
78 models::user_details::get_user_details_by_user_ids(&mut conn, &actor_ids)
79 .await?
80 .into_iter()
81 .map(|details| (details.user_id, (details.first_name, details.last_name)))
82 .collect();
83
84 let res = records
85 .into_iter()
86 .map(|record| {
87 let (actor_first_name, actor_last_name) = actors
88 .get(&record.actor_user_id)
89 .cloned()
90 .unwrap_or_default();
91 CourseCreditRegistrationAction {
92 actor_first_name,
93 actor_last_name,
94 id: record.id,
95 created_at: record.created_at,
96 action: record.action,
97 target_kind: record.target_kind,
98 target_id: record.target_id,
99 actor_user_id: record.actor_user_id,
100 actor_role: record.actor_role,
101 reason: record.reason,
102 before_state: record.before_state,
103 after_state: record.after_state,
104 affected_row_count: record.affected_row_count,
105 }
106 })
107 .collect();
108
109 token.authorized_ok(web::Json(res))
110}
111
112pub fn _add_routes(cfg: &mut ServiceConfig) {
113 cfg.route(
114 "/courses/{course_id}/actions",
115 web::get().to(get_course_credit_registration_actions),
116 );
117}