headless_lms_credit_registration/use_cases/
link_emails.rs1use headless_lms_models::credit_registration_account_linking_emails::{
8 LinkingMailToQueue, claim_unqueued, set_email_delivery_id,
9};
10use headless_lms_models::email_deliveries::insert_email_delivery_to_address;
11use headless_lms_models::email_templates::EmailTemplateType;
12use headless_lms_models::library::credit_registration::account_linking::link_student_number_url;
13use headless_lms_utils::secret_string::expose_option;
14use secrecy::ExposeSecret;
15use serde_json::json;
16use sqlx::{Connection, PgPool};
17
18use crate::error::CreditRegistrationResult;
19use crate::use_cases::mail_queue::{MailQueueSummary, TemplateCache, template_language};
20use crate::workflow::Counts;
21use headless_lms_models::credit_registrations::RegistrationScope;
22
23const QUEUE_LIMIT: i64 = 200;
26
27const TEMPLATE: EmailTemplateType = EmailTemplateType::CreditRegistrationAccountLinking;
28
29pub(crate) async fn run(
31 pool: &PgPool,
32 scope: &RegistrationScope,
33 base_url: &str,
34) -> CreditRegistrationResult<Counts> {
35 let mut conn = pool.acquire().await?;
36 let mut tx = conn.begin().await?;
37 let claimed = claim_unqueued(&mut tx, QUEUE_LIMIT, scope.course_id).await?;
38 let mut templates = TemplateCache::default();
39 let mut summary = MailQueueSummary::new(claimed.len());
40 for mail in &claimed {
41 let language = template_language(&mail.course_language_code);
42 let Some(template_id) = templates.id_for(&mut tx, TEMPLATE, &language).await? else {
43 summary.skip_missing_template(TEMPLATE, &language, language.as_str());
44 continue;
45 };
46 let delivery = insert_email_delivery_to_address(
47 &mut tx,
48 mail.emailed_to.expose_secret(),
49 template_id,
50 &placeholders(base_url, mail),
51 )
52 .await?;
53 set_email_delivery_id(&mut tx, mail.id, delivery).await?;
54 }
55 tx.commit().await?;
56 Ok(summary.finish("No credit_registration_account_linking email template for:"))
57}
58
59fn placeholders(base_url: &str, mail: &LinkingMailToQueue) -> serde_json::Value {
62 json!({
63 "LINK": link_student_number_url(base_url, mail.token.expose_secret()),
64 "NAME": expose_option(&mail.first_names).unwrap_or_default(),
65 "STUDENT_NUMBER": mail.student_number.expose_secret(),
66 "COURSE_NAME": mail.course_name,
67 })
68}