headless_lms_models/
email_deliveries.rs

1use crate::email_templates::EmailTemplateType;
2use crate::prelude::*;
3use std::fmt::Display;
4
5#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
6pub struct EmailDelivery {
7    pub id: Uuid,
8    pub created_at: DateTime<Utc>,
9    pub updated_at: DateTime<Utc>,
10    pub deleted_at: Option<DateTime<Utc>>,
11    pub email_template_id: Uuid,
12    pub error: Option<String>,
13    pub sent: bool,
14    pub user_id: Uuid,
15}
16
17pub struct Email {
18    pub id: Uuid,
19    pub user_id: Uuid,
20    pub to: String,
21    pub subject: Option<String>,
22    pub body: Option<serde_json::Value>,
23    pub template_type: Option<EmailTemplateType>,
24}
25
26pub async fn insert_email_delivery(
27    conn: &mut PgConnection,
28    user_id: Uuid,
29    email_template_id: Uuid,
30) -> ModelResult<Uuid> {
31    let id = Uuid::new_v4();
32
33    sqlx::query!(
34        r#"
35INSERT INTO email_deliveries (
36    id,
37    user_id,
38    email_template_id
39)
40VALUES ($1, $2, $3)
41        "#,
42        id,
43        user_id,
44        email_template_id
45    )
46    .execute(conn)
47    .await?;
48
49    Ok(id)
50}
51
52pub async fn fetch_emails(conn: &mut PgConnection) -> ModelResult<Vec<Email>> {
53    let emails = sqlx::query_as!(
54        Email,
55        r#"
56SELECT
57    ed.id AS id,
58    u.id AS user_id,
59    ud.email AS to,
60    et.subject AS subject,
61    et.content AS body,
62    et.email_template_type AS "template_type: EmailTemplateType"
63FROM email_deliveries ed
64JOIN email_templates et ON et.id = ed.email_template_id
65JOIN users u ON u.id = ed.user_id
66JOIN user_details ud ON ud.user_id = u.id
67WHERE ed.deleted_at IS NULL
68  AND ed.sent = FALSE
69  AND ed.error IS NULL
70LIMIT 10000;
71        "#,
72    )
73    .fetch_all(conn)
74    .await?;
75
76    Ok(emails)
77}
78
79pub async fn mark_as_sent(email_id: Uuid, conn: &mut PgConnection) -> ModelResult<()> {
80    sqlx::query!(
81        "
82update email_deliveries
83set sent = TRUE
84where id = $1;
85    ",
86        email_id
87    )
88    .execute(conn)
89    .await?;
90
91    Ok(())
92}
93
94pub async fn save_err_to_email(
95    email_id: Uuid,
96    err: impl Display,
97    conn: &mut PgConnection,
98) -> ModelResult<()> {
99    sqlx::query!(
100        "
101update email_deliveries
102set sent = FALSE,
103  error = $1
104where id = $2;
105    ",
106        err.to_string(),
107        email_id
108    )
109    .execute(conn)
110    .await?;
111
112    Ok(())
113}