headless_lms_server/domain/credit_registration_phases/
link_emails.rs1use headless_lms_models::credit_registration_account_linking_emails::{
8 LinkingMailToQueue, claim_unqueued, set_email_delivery_id,
9};
10use headless_lms_models::credit_registration_phase_state::PhaseRunOutcome;
11use headless_lms_models::email_deliveries::insert_email_delivery_to_address;
12use headless_lms_models::email_templates::EmailTemplateType;
13use headless_lms_models::library::credit_registration::account_linking::link_student_number_url;
14use secrecy::ExposeSecret;
15use serde_json::json;
16use sqlx::PgConnection;
17use uuid::Uuid;
18
19use super::{MailQueuePhase, PhaseContext, PhaseScope, run_mail_queue_phase, template_language};
20
21const QUEUE_LIMIT: i64 = 200;
24
25pub async fn run(ctx: &PhaseContext<'_>, scope: &PhaseScope) -> anyhow::Result<PhaseRunOutcome> {
26 run_mail_queue_phase::<LinkEmailsPhase>(ctx, scope).await
27}
28
29struct LinkEmailsPhase;
30
31impl MailQueuePhase for LinkEmailsPhase {
32 type Item = LinkingMailToQueue;
33 type Cache = ();
34
35 async fn claim(conn: &mut PgConnection, scope: &PhaseScope) -> anyhow::Result<Vec<Self::Item>> {
36 Ok(claim_unqueued(conn, QUEUE_LIMIT, scope.course_id).await?)
37 }
38
39 fn template_type(_item: &Self::Item) -> EmailTemplateType {
40 EmailTemplateType::CreditRegistrationAccountLinking
41 }
42
43 fn language(item: &Self::Item) -> String {
44 template_language(&item.course_language_code)
45 }
46
47 async fn queue(
48 ctx: &PhaseContext<'_>,
49 conn: &mut PgConnection,
50 item: &Self::Item,
51 template_id: Uuid,
52 _cache: &mut Self::Cache,
53 ) -> anyhow::Result<()> {
54 let delivery = insert_email_delivery_to_address(
55 conn,
56 &item.emailed_to,
57 template_id,
58 &placeholders(ctx.base_url, item),
59 )
60 .await?;
61 set_email_delivery_id(conn, item.id, delivery).await?;
62 Ok(())
63 }
64
65 fn missing_template_label(_template_type: EmailTemplateType, language: &str) -> String {
66 language.to_string()
67 }
68
69 fn missing_templates_error_prefix() -> &'static str {
70 "No credit_registration_account_linking email template for:"
71 }
72}
73
74fn placeholders(base_url: &str, mail: &LinkingMailToQueue) -> serde_json::Value {
77 json!({
78 "LINK": link_student_number_url(base_url, mail.token.expose_secret()),
79 "NAME": mail.first_names.clone().unwrap_or_default(),
80 "STUDENT_NUMBER": mail.student_number,
81 "COURSE_NAME": mail.course_name,
82 })
83}