headless_lms_models/course_module_suotar_configurations/
listing.rs1use crate::credit_registrations::CreditRegistrationErrorCode;
5use crate::prelude::*;
6
7#[derive(Debug, Clone, PartialEq)]
9pub struct ModuleToList {
10 pub course_module_id: Uuid,
11 pub course_id: Uuid,
12 pub uh_course_code: String,
13 pub course_language_code: String,
15}
16
17pub async fn get_active_modules_for_course(
19 conn: &mut PgConnection,
20 course_id: Uuid,
21) -> ModelResult<Vec<ModuleToList>> {
22 let res = sqlx::query_as!(
23 ModuleToList,
24 r#"
25SELECT acm.course_module_id AS "course_module_id!",
26 acm.course_id AS "course_id!",
27 TRIM(cm.uh_course_code) AS "uh_course_code!",
28 co.language_code AS "course_language_code!"
29FROM credit_registration_active_course_modules acm
30 JOIN course_modules cm ON cm.id = acm.course_module_id AND cm.deleted_at IS NULL
31 JOIN courses co ON co.id = acm.course_id AND co.deleted_at IS NULL
32WHERE TRIM(COALESCE(cm.uh_course_code, '')) <> ''
33 AND acm.course_id = $1
34ORDER BY cm.order_number,
35 cm.id
36 "#,
37 course_id,
38 )
39 .fetch_all(conn)
40 .await?;
41 Ok(res)
42}
43
44#[derive(Debug, Clone, PartialEq)]
47pub struct ModuleDiscoveryReport {
48 pub course_id: Uuid,
49 pub course_name: String,
50 pub course_module_id: Uuid,
51 pub course_module_name: Option<String>,
52 pub uh_course_code: Option<String>,
53 pub last_listed_at: Option<DateTime<Utc>>,
54 pub last_listing_attempted_at: Option<DateTime<Utc>>,
55 pub last_listing_error: Option<CreditRegistrationErrorCode>,
56 pub consecutive_listing_failures: i32,
57}
58
59pub async fn get_active_discovery_reports(
61 conn: &mut PgConnection,
62) -> ModelResult<Vec<ModuleDiscoveryReport>> {
63 let res = sqlx::query_as!(
64 ModuleDiscoveryReport,
65 r#"
66SELECT cm.course_id,
67 c.name AS course_name,
68 conf.course_module_id,
69 cm.name AS course_module_name,
70 cm.uh_course_code,
71 conf.last_listed_at,
72 conf.last_listing_attempted_at,
73 conf.last_listing_error AS "last_listing_error?",
74 conf.consecutive_listing_failures
75FROM course_module_suotar_configurations conf
76 JOIN credit_registration_active_course_modules acm ON acm.course_module_id = conf.course_module_id
77 JOIN course_modules cm ON cm.id = conf.course_module_id AND cm.deleted_at IS NULL
78 JOIN courses c ON c.id = cm.course_id AND c.deleted_at IS NULL
79WHERE conf.deleted_at IS NULL
80 AND c.deleted_at IS NULL
81ORDER BY c.name,
82 cm.order_number
83 "#,
84 )
85 .fetch_all(conn)
86 .await?;
87 Ok(res)
88}
89
90pub async fn mark_listing_failed(
93 conn: &mut PgConnection,
94 course_module_id: Uuid,
95 error: CreditRegistrationErrorCode,
96) -> ModelResult<()> {
97 sqlx::query!(
98 r#"
99UPDATE course_module_suotar_configurations
100SET last_listing_attempted_at = now(),
101 last_listing_error = $2,
102 consecutive_listing_failures = consecutive_listing_failures + 1
103WHERE course_module_id = $1
104 AND deleted_at IS NULL
105 "#,
106 course_module_id,
107 error as CreditRegistrationErrorCode,
108 )
109 .execute(conn)
110 .await?;
111 Ok(())
112}
113
114pub async fn mark_listing_succeeded(
118 conn: &mut PgConnection,
119 course_module_id: Uuid,
120 fed_linking: bool,
121) -> ModelResult<()> {
122 sqlx::query!(
123 r#"
124UPDATE course_module_suotar_configurations
125SET last_listed_at = CASE
126 WHEN $2 THEN now()
127 ELSE last_listed_at
128 END,
129 last_listing_attempted_at = now(),
130 last_listing_error = NULL,
131 consecutive_listing_failures = 0
132WHERE course_module_id = $1
133 AND deleted_at IS NULL
134 "#,
135 course_module_id,
136 fed_linking,
137 )
138 .execute(conn)
139 .await?;
140 Ok(())
141}